diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2015-03-27 12:04:12 +0100 |
---|---|---|
committer | Chris Dickinson <christopher.s.dickinson@gmail.com> | 2015-04-28 14:38:16 -0700 |
commit | 36cd5fb9d27b830320e57213f5b8829ffbb93324 (patch) | |
tree | bbab4215d26f8597019135206426fccf27a3089e /deps/v8/src/ic/x87 | |
parent | b57cc51d8d3f4ad279591ae8fa6584ee22773b97 (diff) | |
download | node-new-36cd5fb9d27b830320e57213f5b8829ffbb93324.tar.gz |
deps: upgrade v8 to 4.2.77.13
This commit applies some secondary changes in order to make `make test`
pass cleanly:
* disable broken postmortem debugging in common.gypi
* drop obsolete strict mode test in parallel/test-repl
* drop obsolete test parallel/test-v8-features
PR-URL: https://github.com/iojs/io.js/pull/1232
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Diffstat (limited to 'deps/v8/src/ic/x87')
-rw-r--r-- | deps/v8/src/ic/x87/handler-compiler-x87.cc | 166 | ||||
-rw-r--r-- | deps/v8/src/ic/x87/ic-compiler-x87.cc | 17 | ||||
-rw-r--r-- | deps/v8/src/ic/x87/ic-x87.cc | 168 |
3 files changed, 168 insertions, 183 deletions
diff --git a/deps/v8/src/ic/x87/handler-compiler-x87.cc b/deps/v8/src/ic/x87/handler-compiler-x87.cc index 2ff35954c8..2eb10c3a3b 100644 --- a/deps/v8/src/ic/x87/handler-compiler-x87.cc +++ b/deps/v8/src/ic/x87/handler-compiler-x87.cc @@ -17,22 +17,26 @@ namespace internal { void NamedLoadHandlerCompiler::GenerateLoadViaGetter( - MacroAssembler* masm, Handle<HeapType> type, Register receiver, - Handle<JSFunction> getter) { + MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, + int accessor_index, int expected_arguments, Register scratch) { { FrameScope scope(masm, StackFrame::INTERNAL); - if (!getter.is_null()) { + if (accessor_index >= 0) { + DCHECK(!holder.is(scratch)); + DCHECK(!receiver.is(scratch)); // Call the JavaScript getter with the receiver on the stack. - if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { + if (map->IsJSGlobalObjectMap()) { // Swap in the global receiver. - __ mov(receiver, + __ mov(scratch, FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); + receiver = scratch; } __ push(receiver); ParameterCount actual(0); - ParameterCount expected(getter); - __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, + ParameterCount expected(expected_arguments); + __ LoadAccessor(edi, holder, accessor_index, ACCESSOR_GETTER); + __ InvokeFunction(edi, expected, actual, CALL_FUNCTION, NullCallWrapper()); } else { // If we generate a global code snippet for deoptimization only, remember @@ -137,42 +141,53 @@ void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( // This function uses push() to generate smaller, faster code than // the version above. It is an optimization that should will be removed // when api call ICs are generated in hydrogen. -void PropertyHandlerCompiler::GenerateFastApiCall( +void PropertyHandlerCompiler::GenerateApiAccessorCall( MacroAssembler* masm, const CallOptimization& optimization, - Handle<Map> receiver_map, Register receiver, Register scratch_in, - bool is_store, int argc, Register* values) { + Handle<Map> receiver_map, Register receiver, Register scratch, + bool is_store, Register store_parameter, Register accessor_holder, + int accessor_index) { + DCHECK(!accessor_holder.is(scratch)); // Copy return value. - __ pop(scratch_in); + __ pop(scratch); // receiver __ push(receiver); // Write the arguments to stack frame. - for (int i = 0; i < argc; i++) { - Register arg = values[argc - 1 - i]; - DCHECK(!receiver.is(arg)); - DCHECK(!scratch_in.is(arg)); - __ push(arg); + if (is_store) { + DCHECK(!receiver.is(store_parameter)); + DCHECK(!scratch.is(store_parameter)); + __ push(store_parameter); } - __ push(scratch_in); + __ push(scratch); // Stack now matches JSFunction abi. DCHECK(optimization.is_simple_api_call()); // Abi for CallApiFunctionStub. - Register callee = eax; - Register call_data = ebx; + Register callee = edi; + Register data = ebx; Register holder = ecx; Register api_function_address = edx; - Register scratch = edi; // scratch_in is no longer valid. + scratch = no_reg; + + // Put callee in place. + __ LoadAccessor(callee, accessor_holder, accessor_index, + is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); // Put holder in place. CallOptimization::HolderLookup holder_lookup; - Handle<JSObject> api_holder = - optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); + int holder_depth = 0; + optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, + &holder_depth); switch (holder_lookup) { case CallOptimization::kHolderIsReceiver: __ Move(holder, receiver); break; case CallOptimization::kHolderFound: - __ LoadHeapObject(holder, api_holder); + __ mov(holder, FieldOperand(receiver, HeapObject::kMapOffset)); + __ mov(holder, FieldOperand(holder, Map::kPrototypeOffset)); + for (int i = 1; i < holder_depth; i++) { + __ mov(holder, FieldOperand(holder, HeapObject::kMapOffset)); + __ mov(holder, FieldOperand(holder, Map::kPrototypeOffset)); + } break; case CallOptimization::kHolderNotFound: UNREACHABLE(); @@ -180,23 +195,17 @@ void PropertyHandlerCompiler::GenerateFastApiCall( } Isolate* isolate = masm->isolate(); - Handle<JSFunction> function = optimization.constant_function(); Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); - Handle<Object> call_data_obj(api_call_info->data(), isolate); - - // Put callee in place. - __ LoadHeapObject(callee, function); - bool call_data_undefined = false; - // Put call_data in place. - if (isolate->heap()->InNewSpace(*call_data_obj)) { - __ mov(scratch, api_call_info); - __ mov(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset)); - } else if (call_data_obj->IsUndefined()) { + // Put call data in place. + if (api_call_info->data()->IsUndefined()) { call_data_undefined = true; - __ mov(call_data, Immediate(isolate->factory()->undefined_value())); + __ mov(data, Immediate(isolate->factory()->undefined_value())); } else { - __ mov(call_data, call_data_obj); + __ mov(data, FieldOperand(callee, JSFunction::kSharedFunctionInfoOffset)); + __ mov(data, FieldOperand(data, SharedFunctionInfo::kFunctionDataOffset)); + __ mov(data, FieldOperand(data, FunctionTemplateInfo::kCallCodeOffset)); + __ mov(data, FieldOperand(data, CallHandlerInfo::kDataOffset)); } // Put api_function_address in place. @@ -204,7 +213,7 @@ void PropertyHandlerCompiler::GenerateFastApiCall( __ mov(api_function_address, Immediate(function_address)); // Jump to stub. - CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); + CallApiAccessorStub stub(isolate, is_store, call_data_undefined); __ TailCallStub(&stub); } @@ -217,21 +226,18 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( Register scratch, Label* miss) { Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); DCHECK(cell->value()->IsTheHole()); - Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); - if (masm->serializer_enabled()) { - __ mov(scratch, Immediate(cell)); - __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), - Immediate(the_hole)); - } else { - __ cmp(Operand::ForCell(cell), Immediate(the_hole)); - } + Factory* factory = masm->isolate()->factory(); + Handle<WeakCell> weak_cell = factory->NewWeakCell(cell); + __ LoadWeakValue(scratch, weak_cell, miss); + __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), + Immediate(factory->the_hole_value())); __ j(not_equal, miss); } void NamedStoreHandlerCompiler::GenerateStoreViaSetter( - MacroAssembler* masm, Handle<HeapType> type, Register receiver, - Handle<JSFunction> setter) { + MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, + int accessor_index, int expected_arguments, Register scratch) { // ----------- S t a t e ------------- // -- esp[0] : return address // ----------------------------------- @@ -241,18 +247,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( // Save value register, so we can restore it later. __ push(value()); - if (!setter.is_null()) { + if (accessor_index >= 0) { + DCHECK(!holder.is(scratch)); + DCHECK(!receiver.is(scratch)); + DCHECK(!value().is(scratch)); // Call the JavaScript setter with receiver and value on the stack. - if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { - // Swap in the global receiver. - __ mov(receiver, + if (map->IsJSGlobalObjectMap()) { + __ mov(scratch, FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); + receiver = scratch; } __ push(receiver); __ push(value()); ParameterCount actual(1); - ParameterCount expected(setter); - __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, + ParameterCount expected(expected_arguments); + __ LoadAccessor(edi, holder, accessor_index, ACCESSOR_SETTER); + __ InvokeFunction(edi, expected, actual, CALL_FUNCTION, NullCallWrapper()); } else { // If we generate a global code snippet for deoptimization only, remember @@ -274,16 +284,10 @@ static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, Register holder, Register name, Handle<JSObject> holder_obj) { STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); __ push(name); - Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); - DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); - Register scratch = name; - __ mov(scratch, Immediate(interceptor)); - __ push(scratch); __ push(receiver); __ push(holder); } @@ -385,12 +389,17 @@ void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, Register value_reg, Label* miss_label) { + Register map_reg = scratch1(); + Register scratch = scratch2(); + DCHECK(!value_reg.is(map_reg)); + DCHECK(!value_reg.is(scratch)); __ JumpIfSmi(value_reg, miss_label); HeapType::Iterator<Map> it = field_type->Classes(); if (!it.Done()) { Label do_store; + __ mov(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); while (true) { - __ CompareMap(value_reg, it.Current()); + __ CmpWeakValue(map_reg, Map::WeakCellForMap(it.Current()), scratch); it.Advance(); if (it.Done()) { __ j(not_equal, miss_label); @@ -407,7 +416,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( Register object_reg, Register holder_reg, Register scratch1, Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check) { - Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); + Handle<Map> receiver_map = map(); // Make sure there's no overlap between holder and object registers. DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); @@ -419,8 +428,9 @@ Register PropertyHandlerCompiler::CheckPrototypes( int depth = 0; Handle<JSObject> current = Handle<JSObject>::null(); - if (type()->IsConstant()) - current = Handle<JSObject>::cast(type()->AsConstant()->Value()); + if (receiver_map->IsJSGlobalObjectMap()) { + current = isolate()->global_object(); + } Handle<JSObject> prototype = Handle<JSObject>::null(); Handle<Map> current_map = receiver_map; Handle<Map> holder_map(holder()->map()); @@ -547,12 +557,17 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); __ push(receiver()); // receiver // Push data from ExecutableAccessorInfo. - if (isolate()->heap()->InNewSpace(callback->data())) { - DCHECK(!scratch2().is(reg)); - __ mov(scratch2(), Immediate(callback)); - __ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset)); + Handle<Object> data(callback->data(), isolate()); + if (data->IsUndefined() || data->IsSmi()) { + __ push(Immediate(data)); } else { - __ push(Immediate(Handle<Object>(callback->data(), isolate()))); + DCHECK(!scratch2().is(reg)); + Handle<WeakCell> cell = + isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data)); + // The callback is alive if this instruction is executed, + // so the weak cell is not cleared and points to data. + __ GetWeakValue(scratch2(), cell); + __ push(scratch2()); } __ push(Immediate(isolate()->factory()->undefined_value())); // ReturnValue // ReturnValue default value @@ -677,7 +692,14 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( __ pop(scratch1()); // remove the return address __ push(receiver()); __ push(holder_reg); - __ Push(callback); + // If the callback cannot leak, then push the callback directly, + // otherwise wrap it in a weak cell. + if (callback->data()->IsUndefined() || callback->data()->IsSmi()) { + __ Push(callback); + } else { + Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); + __ Push(cell); + } __ Push(name); __ push(value()); __ push(scratch1()); // restore return address diff --git a/deps/v8/src/ic/x87/ic-compiler-x87.cc b/deps/v8/src/ic/x87/ic-compiler-x87.cc index 89bd937480..160e9e9c67 100644 --- a/deps/v8/src/ic/x87/ic-compiler-x87.cc +++ b/deps/v8/src/ic/x87/ic-compiler-x87.cc @@ -15,8 +15,8 @@ namespace internal { #define __ ACCESS_MASM(masm) -void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, - StrictMode strict_mode) { +void PropertyICCompiler::GenerateRuntimeSetProperty( + MacroAssembler* masm, LanguageMode language_mode) { // Return address is on the stack. DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) && !ebx.is(StoreDescriptor::NameRegister()) && @@ -25,7 +25,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, __ push(StoreDescriptor::ReceiverRegister()); __ push(StoreDescriptor::NameRegister()); __ push(StoreDescriptor::ValueRegister()); - __ push(Immediate(Smi::FromInt(strict_mode))); + __ push(Immediate(Smi::FromInt(language_mode))); __ push(ebx); // return address // Do tail-call to runtime routine. @@ -36,7 +36,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, #undef __ #define __ ACCESS_MASM(masm()) -Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, +Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps, CodeHandleList* handlers, Handle<Name> name, Code::StubType type, @@ -63,7 +63,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, } Label number_case; - Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; + Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss; __ JumpIfSmi(receiver(), smi_target); // Polymorphic keyed stores may use the map register @@ -71,16 +71,15 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, DCHECK(kind() != Code::KEYED_STORE_IC || map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister())); __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); - int receiver_count = types->length(); + int receiver_count = maps->length(); int number_of_handled_maps = 0; for (int current = 0; current < receiver_count; ++current) { - Handle<HeapType> type = types->at(current); - Handle<Map> map = IC::TypeToMap(*type, isolate()); + Handle<Map> map = maps->at(current); if (!map->is_deprecated()) { number_of_handled_maps++; Handle<WeakCell> cell = Map::WeakCellForMap(map); __ CmpWeakValue(map_reg, cell, scratch2()); - if (type->Is(HeapType::Number())) { + if (map->instance_type() == HEAP_NUMBER_TYPE) { DCHECK(!number_case.is_unused()); __ bind(&number_case); } diff --git a/deps/v8/src/ic/x87/ic-x87.cc b/deps/v8/src/ic/x87/ic-x87.cc index 1004ac036b..92005bd097 100644 --- a/deps/v8/src/ic/x87/ic-x87.cc +++ b/deps/v8/src/ic/x87/ic-x87.cc @@ -169,42 +169,65 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, // Loads an indexed element from a fast case array. -// If not_fast_array is NULL, doesn't perform the elements map check. static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register scratch, - Register result, Label* not_fast_array, - Label* out_of_range) { + 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, return_undefined; __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); - if (not_fast_array != NULL) { - // Check that the object is in fast mode and writable. - __ CheckMap(scratch, - masm->isolate()->factory()->fixed_array_map(), - not_fast_array, - DONT_DO_SMI_CHECK); - } else { - __ AssertFastElements(scratch); - } + __ AssertFastElements(scratch); + // Check that the key (index) is within bounds. __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); - __ j(above_equal, out_of_range); + __ 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, &return_undefined); + __ 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), + (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(&return_undefined); + __ 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 consult GetProperty - // to ensure the prototype chain is searched. - __ j(equal, out_of_range); - if (!result.is(scratch)) { - __ mov(result, scratch); - } + // In case the loaded value is the_hole we have to check the prototype chain. + __ j(equal, &check_prototypes); + __ Move(result, scratch); + __ bind(&done); } @@ -307,7 +330,7 @@ static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, } -void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { +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; @@ -329,7 +352,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(eax, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow); + GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); Isolate* isolate = masm->isolate(); Counters* counters = isolate->counters(); __ IncrementCounter(counters->keyed_load_generic_smi(), 1); @@ -369,95 +392,36 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor, &slow); - // If the receiver is a fast-case object, check the keyed lookup - // cache. Otherwise probe the dictionary. + // 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 receiver's map is still in eax, compute the keyed lookup cache hash - // based on 32 bits of the map pointer and the string hash. - if (FLAG_debug_code) { - __ cmp(eax, FieldOperand(receiver, HeapObject::kMapOffset)); - __ Check(equal, kMapIsNoLongerInEax); - } - __ mov(ebx, eax); // Keep the map around for later. - __ shr(eax, KeyedLookupCache::kMapHashShift); - __ mov(edi, FieldOperand(key, String::kHashFieldOffset)); - __ shr(edi, String::kHashShift); - __ xor_(eax, edi); - __ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); - - // Load the key (consisting of map and internalized string) from the cache and - // check for match. - Label load_in_object_property; - static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; - Label hit_on_nth_entry[kEntriesPerBucket]; - ExternalReference cache_keys = - ExternalReference::keyed_lookup_cache_keys(masm->isolate()); - - for (int i = 0; i < kEntriesPerBucket - 1; i++) { - Label try_next_entry; - __ mov(edi, eax); - __ shl(edi, kPointerSizeLog2 + 1); - if (i != 0) { - __ add(edi, Immediate(kPointerSize * i * 2)); - } - __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); - __ j(not_equal, &try_next_entry); - __ add(edi, Immediate(kPointerSize)); - __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys)); - __ j(equal, &hit_on_nth_entry[i]); - __ bind(&try_next_entry); + if (FLAG_vector_ics) { + // When vector ics are in use, 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<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + isolate->factory()->keyed_load_dummy_vector()); + int slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ push(Immediate(Smi::FromInt(slot))); + __ push(Immediate(dummy_vector)); } - __ lea(edi, Operand(eax, 1)); - __ shl(edi, kPointerSizeLog2 + 1); - __ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2)); - __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); - __ j(not_equal, &slow); - __ add(edi, Immediate(kPointerSize)); - __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys)); - __ j(not_equal, &slow); + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( + Code::ComputeHandlerFlags(Code::LOAD_IC)); + masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags, + false, receiver, key, ebx, edi); - // Get field offset. - // ebx : receiver's map - // eax : lookup cache index - ExternalReference cache_field_offsets = - ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); - - // Hit on nth entry. - for (int i = kEntriesPerBucket - 1; i >= 0; i--) { - __ bind(&hit_on_nth_entry[i]); - if (i != 0) { - __ add(eax, Immediate(i)); - } - __ mov(edi, - Operand::StaticArray(eax, times_pointer_size, cache_field_offsets)); - __ movzx_b(eax, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); - __ sub(edi, eax); - __ j(above_equal, &property_array_property); - if (i != 0) { - __ jmp(&load_in_object_property); - } + if (FLAG_vector_ics) { + __ pop(VectorLoadICDescriptor::VectorRegister()); + __ pop(VectorLoadICDescriptor::SlotRegister()); } - // Load in-object property. - __ bind(&load_in_object_property); - __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset)); - __ add(eax, edi); - __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0)); - __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); - __ ret(0); - - // Load property array property. - __ bind(&property_array_property); - __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset)); - __ mov(eax, - FieldOperand(eax, edi, times_pointer_size, FixedArray::kHeaderSize)); - __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); - __ ret(0); + // Cache miss. + GenerateMiss(masm); // Do a quick inline probe of the receiver's dictionary, if it // exists. @@ -648,7 +612,7 @@ static void KeyedStoreGenerateMegamorphicHelper( void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, - StrictMode strict_mode) { + LanguageMode language_mode) { // Return address is on the stack. Label slow, fast_object, fast_object_grow; Label fast_double, fast_double_grow; @@ -685,7 +649,7 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, // Slow case: call runtime. __ bind(&slow); - PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); + PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); // Never returns to here. __ bind(&maybe_name_key); |