From c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7a Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Wed, 8 Mar 2017 14:04:23 +0000 Subject: Merge V8 5.6.326.50 Test: manual, ran D8, tested connecting through PAC proxy. Change-Id: I6067097f8ded999e9930a7dfd2fdc3733d7c6284 --- src/ic/ia32/access-compiler-ia32.cc | 21 ++- src/ic/ia32/handler-compiler-ia32.cc | 71 +++++----- src/ic/ia32/ic-ia32.cc | 244 ----------------------------------- 3 files changed, 43 insertions(+), 293 deletions(-) (limited to 'src/ic/ia32') diff --git a/src/ic/ia32/access-compiler-ia32.cc b/src/ic/ia32/access-compiler-ia32.cc index 3219f3d1..411c7446 100644 --- a/src/ic/ia32/access-compiler-ia32.cc +++ b/src/ic/ia32/access-compiler-ia32.cc @@ -16,22 +16,21 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, __ jmp(code, RelocInfo::CODE_TARGET); } - -Register* PropertyAccessCompiler::load_calling_convention() { - // receiver, name, scratch1, scratch2, scratch3. +void PropertyAccessCompiler::InitializePlatformSpecific( + AccessCompilerData* data) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - static Register registers[] = {receiver, name, ebx, eax, edi}; - return registers; -} + // Load calling convention. + // receiver, name, scratch1, scratch2, scratch3. + Register load_registers[] = {receiver, name, ebx, eax, edi}; -Register* PropertyAccessCompiler::store_calling_convention() { + // Store calling convention. // receiver, name, scratch1, scratch2. - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - static Register registers[] = {receiver, name, ebx, edi}; - return registers; + Register store_registers[] = {receiver, name, ebx, edi}; + + data->Initialize(arraysize(load_registers), load_registers, + arraysize(store_registers), store_registers); } #undef __ diff --git a/src/ic/ia32/handler-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc index 06c58b8a..68fd1b9d 100644 --- a/src/ic/ia32/handler-compiler-ia32.cc +++ b/src/ic/ia32/handler-compiler-ia32.cc @@ -411,10 +411,32 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, } } +void PropertyHandlerCompiler::GenerateAccessCheck( + Handle native_context_cell, Register scratch1, Register scratch2, + Label* miss, bool compare_native_contexts_only) { + Label done; + // Load current native context. + __ mov(scratch1, NativeContextOperand()); + // Load expected native context. + __ LoadWeakValue(scratch2, native_context_cell, miss); + __ cmp(scratch1, scratch2); + + if (!compare_native_contexts_only) { + __ j(equal, &done); + + // Compare security tokens of current and expected native contexts. + __ mov(scratch1, ContextOperand(scratch1, Context::SECURITY_TOKEN_INDEX)); + __ mov(scratch2, ContextOperand(scratch2, Context::SECURITY_TOKEN_INDEX)); + __ cmp(scratch1, scratch2); + } + __ j(not_equal, miss); + + __ bind(&done); +} Register PropertyHandlerCompiler::CheckPrototypes( Register object_reg, Register holder_reg, Register scratch1, - Register scratch2, Handle name, Label* miss, PrototypeCheckType check, + Register scratch2, Handle name, Label* miss, ReturnHolder return_what) { Handle receiver_map = map(); @@ -433,17 +455,6 @@ Register PropertyHandlerCompiler::CheckPrototypes( __ j(not_equal, miss); } - // The prototype chain of primitives (and their JSValue wrappers) depends - // on the native context, which can't be guarded by validity cells. - // |object_reg| holds the native context specific prototype in this case; - // we need to check its map. - if (check == CHECK_ALL_MAPS) { - __ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset)); - Handle cell = Map::WeakCellForMap(receiver_map); - __ CmpWeakValue(scratch1, cell, scratch2); - __ j(not_equal, miss); - } - // Keep track of the current object in register reg. Register reg = object_reg; int depth = 0; @@ -453,46 +464,28 @@ Register PropertyHandlerCompiler::CheckPrototypes( current = isolate()->global_object(); } - // Check access rights to the global object. This has to happen after - // the map check so that we know that the object is actually a global - // object. - // This allows us to install generated handlers for accesses to the - // global proxy (as opposed to using slow ICs). See corresponding code - // in LookupForRead(). - if (receiver_map->IsJSGlobalProxyMap()) { - __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); - } - - Handle prototype = Handle::null(); - Handle current_map = receiver_map; + Handle current_map(receiver_map->GetPrototypeChainRootMap(isolate()), + isolate()); Handle holder_map(holder()->map()); // Traverse the prototype chain and check the maps in the prototype chain for // fast and global objects or do negative lookup for normal objects. while (!current_map.is_identical_to(holder_map)) { ++depth; - // Only global objects and objects that do not require access - // checks are allowed in stubs. - DCHECK(current_map->IsJSGlobalProxyMap() || - !current_map->is_access_check_needed()); - - prototype = handle(JSObject::cast(current_map->prototype())); if (current_map->IsJSGlobalObjectMap()) { GenerateCheckPropertyCell(masm(), Handle::cast(current), name, scratch2, miss); } else if (current_map->is_dictionary_map()) { DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. - if (!name->IsUniqueName()) { - DCHECK(name->IsString()); - name = factory()->InternalizeString(Handle::cast(name)); - } + DCHECK(name->IsUniqueName()); DCHECK(current.is_null() || current->property_dictionary()->FindEntry(name) == NameDictionary::kNotFound); if (depth > 1) { - // TODO(jkummerow): Cache and re-use weak cell. - __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); + Handle weak_cell = + Map::GetOrCreatePrototypeWeakCell(current, isolate()); + __ LoadWeakValue(reg, weak_cell, miss); } GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, scratch2); @@ -500,7 +493,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( reg = holder_reg; // From now on the object will be in holder_reg. // Go to the next object in the prototype chain. - current = prototype; + current = handle(JSObject::cast(current_map->prototype())); current_map = handle(current->map()); } @@ -511,7 +504,9 @@ Register PropertyHandlerCompiler::CheckPrototypes( bool return_holder = return_what == RETURN_HOLDER; if (return_holder && depth != 0) { - __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); + Handle weak_cell = + Map::GetOrCreatePrototypeWeakCell(current, isolate()); + __ LoadWeakValue(reg, weak_cell, miss); } // Return the register containing the holder. diff --git a/src/ic/ia32/ic-ia32.cc b/src/ic/ia32/ic-ia32.cc index b7496d46..44a5b9f5 100644 --- a/src/ic/ia32/ic-ia32.cc +++ b/src/ic/ia32/ic-ia32.cc @@ -18,18 +18,6 @@ namespace internal { #define __ ACCESS_MASM(masm) - -static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type, - Label* global_object) { - // Register usage: - // type: holds the receiver instance type on entry. - __ cmp(type, JS_GLOBAL_OBJECT_TYPE); - __ j(equal, global_object); - __ cmp(type, JS_GLOBAL_PROXY_TYPE); - __ j(equal, global_object); -} - - // Helper function used to load a property from a dictionary backing // storage. This function may fail to load a property even though it is // in the dictionary, so code at miss_label must always call a backup @@ -132,238 +120,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss_label, __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); } - -// Checks the receiver for special cases (value type, slow case bits). -// Falls through for regular JS object. -static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, - Register receiver, Register map, - int interceptor_bit, Label* slow) { - // Register use: - // receiver - holds the receiver and is unchanged. - // Scratch registers: - // map - used to hold the map of the receiver. - - // Check that the object isn't a smi. - __ JumpIfSmi(receiver, slow); - - // Get the map of the receiver. - __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); - - // Check bit field. - __ test_b( - FieldOperand(map, Map::kBitFieldOffset), - Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); - __ j(not_zero, slow); - // Check that the object is some kind of JS object EXCEPT JS Value type. In - // the case that the object is a value-wrapper object, we enter the runtime - // system to make sure that indexing into string objects works as intended. - DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); - - __ CmpInstanceType(map, JS_OBJECT_TYPE); - __ j(below, slow); -} - - -// Loads an indexed element from a fast case array. -static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, - Register key, Register scratch, - Register scratch2, Register result, - Label* slow) { - // Register use: - // receiver - holds the receiver and is unchanged. - // key - holds the key and is unchanged (must be a smi). - // Scratch registers: - // scratch - used to hold elements of the receiver and the loaded value. - // scratch2 - holds maps and prototypes during prototype chain check. - // result - holds the result on exit if the load succeeds and - // we fall through. - Label check_prototypes, check_next_prototype; - Label done, in_bounds, absent; - - __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); - __ AssertFastElements(scratch); - - // Check that the key (index) is within bounds. - __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); - __ j(below, &in_bounds); - // Out-of-bounds. Check the prototype chain to see if we can just return - // 'undefined'. - __ cmp(key, 0); - __ j(less, slow); // Negative keys can't take the fast OOB path. - __ bind(&check_prototypes); - __ mov(scratch2, FieldOperand(receiver, HeapObject::kMapOffset)); - __ bind(&check_next_prototype); - __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset)); - // scratch2: current prototype - __ cmp(scratch2, masm->isolate()->factory()->null_value()); - __ j(equal, &absent); - __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset)); - __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset)); - // scratch: elements of current prototype - // scratch2: map of current prototype - __ CmpInstanceType(scratch2, JS_OBJECT_TYPE); - __ j(below, slow); - __ test_b(FieldOperand(scratch2, Map::kBitFieldOffset), - Immediate((1 << Map::kIsAccessCheckNeeded) | - (1 << Map::kHasIndexedInterceptor))); - __ j(not_zero, slow); - __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array()); - __ j(not_equal, slow); - __ jmp(&check_next_prototype); - - __ bind(&absent); - __ mov(result, masm->isolate()->factory()->undefined_value()); - __ jmp(&done); - - __ bind(&in_bounds); - // Fast case: Do the load. - STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); - __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); - __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); - // In case the loaded value is the_hole we have to check the prototype chain. - __ j(equal, &check_prototypes); - __ Move(result, scratch); - __ bind(&done); -} - - -// Checks whether a key is an array index string or a unique name. -// Falls through if the key is a unique name. -static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, - Register map, Register hash, - Label* index_string, Label* not_unique) { - // Register use: - // key - holds the key and is unchanged. Assumed to be non-smi. - // Scratch registers: - // map - used to hold the map of the key. - // hash - used to hold the hash of the key. - Label unique; - __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); - __ j(above, not_unique); - STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); - __ j(equal, &unique); - - // Is the string an array index, with cached numeric value? - __ mov(hash, FieldOperand(key, Name::kHashFieldOffset)); - __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask)); - __ j(zero, index_string); - - // Is the string internalized? We already know it's a string so a single - // bit test is enough. - STATIC_ASSERT(kNotInternalizedTag != 0); - __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), - Immediate(kIsNotInternalizedMask)); - __ j(not_zero, not_unique); - - __ bind(&unique); -} - -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { - // The return address is on the stack. - Label slow, check_name, index_smi, index_name, property_array_property; - Label probe_dictionary, check_number_dictionary; - - Register receiver = LoadDescriptor::ReceiverRegister(); - Register key = LoadDescriptor::NameRegister(); - DCHECK(receiver.is(edx)); - DCHECK(key.is(ecx)); - - // Check that the key is a smi. - __ JumpIfNotSmi(key, &check_name); - __ bind(&index_smi); - // Now the key is known to be a smi. This place is also jumped to from - // where a numeric string is converted to a smi. - - GenerateKeyedLoadReceiverCheck(masm, receiver, eax, - Map::kHasIndexedInterceptor, &slow); - - // Check the receiver's map to see if it has fast elements. - __ CheckFastElements(eax, &check_number_dictionary); - - GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); - Isolate* isolate = masm->isolate(); - Counters* counters = isolate->counters(); - __ IncrementCounter(counters->ic_keyed_load_generic_smi(), 1); - __ ret(0); - - __ bind(&check_number_dictionary); - __ mov(ebx, key); - __ SmiUntag(ebx); - __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); - - // Check whether the elements is a number dictionary. - // ebx: untagged index - // eax: elements - __ CheckMap(eax, isolate->factory()->hash_table_map(), &slow, - DONT_DO_SMI_CHECK); - Label slow_pop_receiver; - // Push receiver on the stack to free up a register for the dictionary - // probing. - __ push(receiver); - __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax); - // Pop receiver before returning. - __ pop(receiver); - __ ret(0); - - __ bind(&slow_pop_receiver); - // Pop the receiver from the stack and jump to runtime. - __ pop(receiver); - - __ bind(&slow); - // Slow case: jump to runtime. - __ IncrementCounter(counters->ic_keyed_load_generic_slow(), 1); - GenerateRuntimeGetProperty(masm); - - __ bind(&check_name); - GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); - - GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor, - &slow); - - // If the receiver is a fast-case object, check the stub cache. Otherwise - // probe the dictionary. - __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); - __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), - Immediate(isolate->factory()->hash_table_map())); - __ j(equal, &probe_dictionary); - - // The handlers in the stub cache expect a vector and slot. Since we won't - // change the IC from any downstream misses, a dummy vector can be used. - Handle dummy_vector = - TypeFeedbackVector::DummyVector(isolate); - int slot = dummy_vector->GetIndex( - FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot)); - __ push(Immediate(Smi::FromInt(slot))); - __ push(Immediate(dummy_vector)); - - masm->isolate()->load_stub_cache()->GenerateProbe(masm, receiver, key, ebx, - edi); - - __ pop(LoadWithVectorDescriptor::VectorRegister()); - __ pop(LoadDescriptor::SlotRegister()); - - // Cache miss. - GenerateMiss(masm); - - // Do a quick inline probe of the receiver's dictionary, if it - // exists. - __ bind(&probe_dictionary); - - __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset)); - __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); - GenerateGlobalInstanceTypeCheck(masm, eax, &slow); - - GenerateDictionaryLoad(masm, &slow, ebx, key, eax, edi, eax); - __ IncrementCounter(counters->ic_keyed_load_generic_symbol(), 1); - __ ret(0); - - __ bind(&index_name); - __ IndexFromHash(ebx, key); - // Now jump to the place where smi keys are handled. - __ jmp(&index_smi); -} - - static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { -- cgit v1.2.3