diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-08-23 06:09:40 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-09-06 21:38:01 +1000 |
commit | 9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch) | |
tree | 4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/ic | |
parent | 46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff) | |
download | android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.gz android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.bz2 android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.zip |
deps: upgrade V8 to 4.5.103.24
Upgrade to the latest branch-head for V8 4.5. For the full commit log see
https://github.com/v8/v8-git-mirror/commits/4.5.103.24
PR-URL: https://github.com/nodejs/node/pull/2509
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/ic')
53 files changed, 1303 insertions, 1998 deletions
diff --git a/deps/v8/src/ic/access-compiler.cc b/deps/v8/src/ic/access-compiler.cc index c3bf11c439..6fffeda08b 100644 --- a/deps/v8/src/ic/access-compiler.cc +++ b/deps/v8/src/ic/access-compiler.cc @@ -51,5 +51,5 @@ Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) { DCHECK(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC); return store_calling_convention(); } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/access-compiler.h b/deps/v8/src/ic/access-compiler.h index fe4369a1ad..61567a2224 100644 --- a/deps/v8/src/ic/access-compiler.h +++ b/deps/v8/src/ic/access-compiler.h @@ -54,14 +54,8 @@ class PropertyAccessCompiler BASE_EMBEDDED { Register receiver() const { return registers_[0]; } Register name() const { return registers_[1]; } - Register slot() const { - DCHECK(FLAG_vector_ics); - return VectorLoadICDescriptor::SlotRegister(); - } - Register vector() const { - DCHECK(FLAG_vector_ics); - return VectorLoadICDescriptor::VectorRegister(); - } + Register slot() const { return LoadDescriptor::SlotRegister(); } + Register vector() const { return LoadWithVectorDescriptor::VectorRegister(); } Register scratch1() const { return registers_[2]; } Register scratch2() const { return registers_[3]; } Register scratch3() const { return registers_[4]; } diff --git a/deps/v8/src/ic/arm/access-compiler-arm.cc b/deps/v8/src/ic/arm/access-compiler-arm.cc index 4a4d688c05..73ef09663e 100644 --- a/deps/v8/src/ic/arm/access-compiler-arm.cc +++ b/deps/v8/src/ic/arm/access-compiler-arm.cc @@ -40,7 +40,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/arm/handler-compiler-arm.cc b/deps/v8/src/ic/arm/handler-compiler-arm.cc index 0343193c22..6af65e2cf2 100644 --- a/deps/v8/src/ic/arm/handler-compiler-arm.cc +++ b/deps/v8/src/ic/arm/handler-compiler-arm.cc @@ -788,7 +788,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/ic/arm/ic-arm.cc b/deps/v8/src/ic/arm/ic-arm.cc index 093a7c1bb2..a3b74ce9f3 100644 --- a/deps/v8/src/ic/arm/ic-arm.cc +++ b/deps/v8/src/ic/arm/ic-arm.cc @@ -161,7 +161,8 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch1, Register scratch2, - Register result, Label* slow) { + Register result, Label* slow, + LanguageMode language_mode) { // Register use: // // receiver - holds the receiver on entry. @@ -183,7 +184,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // // scratch2 - used to hold maps, prototypes, and the loaded value. Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(elements); @@ -202,7 +203,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ CompareRoot(scratch2, Heap::kNullValueRootIndex); - __ b(eq, &return_undefined); + __ b(eq, &absent); __ ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); __ ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -217,9 +218,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ b(ne, slow); __ jmp(&check_next_prototype); - __ bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ jmp(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ jmp(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ jmp(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -263,7 +269,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = r0; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -278,7 +284,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } @@ -289,14 +295,10 @@ static const Register LoadIC_TempRegister() { return r3; } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); - __ Push(receiver, name, slot, vector); - } else { - __ Push(receiver, name); - } + __ Push(receiver, name, slot, vector); } @@ -304,136 +306,30 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in lr. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->load_miss(), 1, r4, r5); LoadIC_PushArgs(masm); // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); -} - - -static MemOperand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Register scratch3, Label* unmapped_case, - Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the map check - // later, we do not need to check for interceptors or whether it - // requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_RECEIVER_TYPE); - __ b(lt, slow_case); - - // Check that the key is a positive smi. - __ tst(key, Operand(0x80000001)); - __ b(ne, slow_case); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ ldr(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ ldr(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); - __ sub(scratch2, scratch2, Operand(Smi::FromInt(2))); - __ cmp(key, Operand(scratch2)); - __ b(cs, unmapped_case); - - // Load element index and check whether it is the hole. - const int kOffset = - FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; - - __ mov(scratch3, Operand(kPointerSize >> 1)); - __ mul(scratch3, key, scratch3); - __ add(scratch3, scratch3, Operand(kOffset)); - - __ ldr(scratch2, MemOperand(scratch1, scratch3)); - __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - __ cmp(scratch2, scratch3); - __ b(eq, unmapped_case); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - __ ldr(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); - __ mov(scratch3, Operand(kPointerSize >> 1)); - __ mul(scratch3, scratch2, scratch3); - __ add(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag)); - return MemOperand(scratch1, scratch3); -} - - -static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. The parameter_map register - // must be loaded with the parameter map of the arguments object and is - // overwritten. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, scratch, fixed_array_map, slow_case, - DONT_DO_SMI_CHECK); - __ ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); - __ cmp(key, Operand(scratch)); - __ b(cs, slow_case); - __ mov(scratch, Operand(kPointerSize >> 1)); - __ mul(scratch, key, scratch); - __ add(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - return MemOperand(backing_store, scratch); -} - - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(receiver.is(r1)); - DCHECK(key.is(r2)); - DCHECK(value.is(r0)); - - Label slow, notin; - MemOperand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, key, r3, r4, r5, ¬in, &slow); - __ str(value, mapped_location); - __ add(r6, r3, r5); - __ mov(r9, value); - __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs); - __ Ret(); - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in r3. - MemOperand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, key, r3, r4, &slow); - __ str(value, unmapped_location); - __ add(r6, r3, r4); - __ mov(r9, value); - __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs); - __ Ret(); - __ bind(&slow); - GenerateMiss(masm); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -441,9 +337,8 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in lr. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r4, r5); LoadIC_PushArgs(masm); @@ -451,21 +346,27 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Perform tail call to the entry. + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -489,7 +390,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(r0, r3, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow); + GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow, + language_mode); __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); __ Ret(); @@ -511,7 +413,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4, r3); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); @@ -527,20 +429,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ cmp(r4, ip); __ b(eq, &probe_dictionary); - - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(vector, slot, r4, r5, r6, r9)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); - __ mov(slot, Operand(Smi::FromInt(int_slot))); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, r4, r5, r6, r9)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); + __ mov(slot, Operand(Smi::FromInt(slot_index))); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -784,6 +682,20 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ ldr(r4, FieldMemOperand(key, HeapObject::kMapOffset)); __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(r4, &slow); + + if (FLAG_vector_stores) { + // 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. + Register vector = VectorStoreICDescriptor::VectorRegister(); + Register slot = VectorStoreICDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, r3, r4, r5, r6)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedStoreDummyVectorRootIndex); + __ mov(slot, Operand(Smi::FromInt(slot_index))); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -984,7 +896,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.EmitCondition(eq); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/ic/arm/ic-compiler-arm.cc b/deps/v8/src/ic/arm/ic-compiler-arm.cc index c5c0b7057e..e42f2f7898 100644 --- a/deps/v8/src/ic/arm/ic-compiler-arm.cc +++ b/deps/v8/src/ic/arm/ic-compiler-arm.cc @@ -128,7 +128,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/ic/arm/stub-cache-arm.cc b/deps/v8/src/ic/arm/stub-cache-arm.cc index 1d6bd30b76..aa247d230f 100644 --- a/deps/v8/src/ic/arm/stub-cache-arm.cc +++ b/deps/v8/src/ic/arm/stub-cache-arm.cc @@ -125,8 +125,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // extra3 don't conflict with the vector and slot registers, which need // to be preserved for a handler call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); } #endif @@ -175,7 +175,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/ic/arm64/access-compiler-arm64.cc b/deps/v8/src/ic/arm64/access-compiler-arm64.cc index 58e6099ae6..e77476f0a8 100644 --- a/deps/v8/src/ic/arm64/access-compiler-arm64.cc +++ b/deps/v8/src/ic/arm64/access-compiler-arm64.cc @@ -47,7 +47,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM64 diff --git a/deps/v8/src/ic/arm64/handler-compiler-arm64.cc b/deps/v8/src/ic/arm64/handler-compiler-arm64.cc index 516bf640d9..3986c0ed66 100644 --- a/deps/v8/src/ic/arm64/handler-compiler-arm64.cc +++ b/deps/v8/src/ic/arm64/handler-compiler-arm64.cc @@ -800,7 +800,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/arm64/ic-arm64.cc b/deps/v8/src/ic/arm64/ic-arm64.cc index bae6ac33cf..13dd3913ae 100644 --- a/deps/v8/src/ic/arm64/ic-arm64.cc +++ b/deps/v8/src/ic/arm64/ic-arm64.cc @@ -167,11 +167,12 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch1, Register scratch2, - Register result, Label* slow) { + Register result, Label* slow, + LanguageMode language_mode) { DCHECK(!AreAliased(receiver, key, elements, scratch1, scratch2)); Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; // Check for fast array. __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); @@ -191,7 +192,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ Bind(&check_next_prototype); __ Ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype - __ JumpIfRoot(scratch2, Heap::kNullValueRootIndex, &return_undefined); + __ JumpIfRoot(scratch2, Heap::kNullValueRootIndex, &absent); __ Ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); __ Ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -204,9 +205,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ JumpIfNotRoot(elements, Heap::kEmptyFixedArrayRootIndex, slow); __ B(&check_next_prototype); - __ Bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ B(&done); + __ Bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ B(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ B(&done); + } __ Bind(&in_bounds); // Fast case: Do the load. @@ -258,94 +264,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -// Neither 'object' nor 'key' are modified by this function. -// -// If the 'unmapped_case' or 'slow_case' exit is taken, the 'map' register is -// left with the object's elements map. Otherwise, it is used as a scratch -// register. -static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, - Register object, Register key, - Register map, Register scratch1, - Register scratch2, - Label* unmapped_case, - Label* slow_case) { - DCHECK(!AreAliased(object, key, map, scratch1, scratch2)); - - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the elements - // map check later, we do not need to check for interceptors or - // whether it requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ JumpIfObjectType(object, map, scratch1, FIRST_JS_RECEIVER_TYPE, slow_case, - lt); - - // Check that the key is a positive smi. - __ JumpIfNotSmi(key, slow_case); - __ Tbnz(key, kXSignBit, slow_case); - - // Load the elements object and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ Ldr(map, FieldMemOperand(object, JSObject::kElementsOffset)); - __ CheckMap(map, scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup. - __ Ldr(scratch1, FieldMemOperand(map, FixedArray::kLengthOffset)); - __ Sub(scratch1, scratch1, Smi::FromInt(2)); - __ Cmp(key, scratch1); - __ B(hs, unmapped_case); - - // Load element index and check whether it is the hole. - static const int offset = - FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; - - __ Add(scratch1, map, offset); - __ SmiUntag(scratch2, key); - __ Ldr(scratch1, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2)); - __ JumpIfRoot(scratch1, Heap::kTheHoleValueRootIndex, unmapped_case); - - // Load value from context and return it. - __ Ldr(scratch2, FieldMemOperand(map, FixedArray::kHeaderSize)); - __ SmiUntag(scratch1); - __ Lsl(scratch1, scratch1, kPointerSizeLog2); - __ Add(scratch1, scratch1, Context::kHeaderSize - kHeapObjectTag); - // The base of the result (scratch2) is passed to RecordWrite in - // KeyedStoreIC::GenerateSloppyArguments and it must be a HeapObject. - return MemOperand(scratch2, scratch1); -} - - -// The 'parameter_map' register must be loaded with the parameter map of the -// arguments object and is overwritten. -static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - DCHECK(!AreAliased(key, parameter_map, scratch)); - - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ Ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, scratch, fixed_array_map, slow_case, - DONT_DO_SMI_CHECK); - __ Ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); - __ Cmp(key, scratch); - __ B(hs, slow_case); - - __ Add(backing_store, backing_store, - FixedArray::kHeaderSize - kHeapObjectTag); - __ SmiUntag(scratch, key); - return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2); -} - - -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = x0; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -359,7 +278,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ Bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } @@ -368,76 +287,30 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { Isolate* isolate = masm->isolate(); ASM_LOCATION("LoadIC::GenerateMiss"); - DCHECK(!FLAG_vector_ics || - !AreAliased(x4, x5, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(x4, x5, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->load_miss(), 1, x4, x5); // Perform tail call to the entry. - if (FLAG_vector_ics) { - __ Push(VectorLoadICDescriptor::ReceiverRegister(), - VectorLoadICDescriptor::NameRegister(), - VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister()); - } else { - __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - } + __ Push(LoadWithVectorDescriptor::ReceiverRegister(), + LoadWithVectorDescriptor::NameRegister(), + LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister()); ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); -} - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); - Label slow, notin; - Register value = StoreDescriptor::ValueRegister(); - Register key = StoreDescriptor::NameRegister(); - Register receiver = StoreDescriptor::ReceiverRegister(); - DCHECK(receiver.is(x1)); - DCHECK(key.is(x2)); - DCHECK(value.is(x0)); - - Register map = x3; - - // These registers are used by GenerateMappedArgumentsLookup to build a - // MemOperand. They are live for as long as the MemOperand is live. - Register mapped1 = x4; - Register mapped2 = x5; - - MemOperand mapped = GenerateMappedArgumentsLookup( - masm, receiver, key, map, mapped1, mapped2, ¬in, &slow); - Operand mapped_offset = mapped.OffsetAsOperand(); - __ Str(value, mapped); - __ Add(x10, mapped.base(), mapped_offset); - __ Mov(x11, value); - __ RecordWrite(mapped.base(), x10, x11, kLRHasNotBeenSaved, kDontSaveFPRegs); - __ Ret(); - - __ Bind(¬in); - - // These registers are used by GenerateMappedArgumentsLookup to build a - // MemOperand. They are live for as long as the MemOperand is live. - Register unmapped1 = map; // This is assumed to alias 'map'. - Register unmapped2 = x4; - MemOperand unmapped = - GenerateUnmappedArgumentsLookup(masm, key, unmapped1, unmapped2, &slow); - Operand unmapped_offset = unmapped.OffsetAsOperand(); - __ Str(value, unmapped); - __ Add(x10, unmapped.base(), unmapped_offset); - __ Mov(x11, value); - __ RecordWrite(unmapped.base(), x10, x11, kLRHasNotBeenSaved, - kDontSaveFPRegs); - __ Ret(); - __ Bind(&slow); - GenerateMiss(masm); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -445,32 +318,32 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in lr. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(x10, x11, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(x10, x11, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11); - if (FLAG_vector_ics) { - __ Push(VectorLoadICDescriptor::ReceiverRegister(), - VectorLoadICDescriptor::NameRegister(), - VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister()); - } else { - __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - } + __ Push(LoadWithVectorDescriptor::ReceiverRegister(), + LoadWithVectorDescriptor::NameRegister(), + LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister()); // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } @@ -478,7 +351,8 @@ static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key, Register receiver, Register scratch1, Register scratch2, Register scratch3, Register scratch4, Register scratch5, - Label* slow) { + Label* slow, + LanguageMode language_mode) { DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4, scratch5)); @@ -494,7 +368,7 @@ static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key, __ CheckFastElements(scratch1, scratch2, &check_number_dictionary); GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1, - result, slow); + result, slow, language_mode); __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, scratch1, scratch2); __ Ret(); @@ -533,19 +407,16 @@ static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key, __ Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset)); __ JumpIfRoot(scratch3, Heap::kHashTableMapRootIndex, &probe_dictionary); - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(vector, slot, scratch1, scratch2, scratch3, scratch4)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); - __ Mov(slot, Operand(Smi::FromInt(int_slot))); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, scratch1, scratch2, scratch3, scratch4)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); + __ Mov(slot, Operand(Smi::FromInt(slot_index))); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -568,7 +439,8 @@ static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key, } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. Label slow, check_name, index_smi, index_name; @@ -581,13 +453,14 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ Bind(&index_smi); // Now the key is known to be a smi. This place is also jumped to from below // where a numeric string is converted to a smi. - GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow); + GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow, + language_mode); // Slow case. __ Bind(&slow); __ IncrementCounter(masm->isolate()->counters()->keyed_load_generic_slow(), 1, x4, x3); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ Bind(&check_name); GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow); @@ -809,6 +682,20 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ Ldr(x10, FieldMemOperand(key, HeapObject::kMapOffset)); __ Ldrb(x10, FieldMemOperand(x10, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(x10, &slow); + + if (FLAG_vector_stores) { + // 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. + Register vector = VectorStoreICDescriptor::VectorRegister(); + Register slot = VectorStoreICDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, x3, x4, x5, x6)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedStoreDummyVectorRootIndex); + __ Mov(slot, Operand(Smi::FromInt(slot_index))); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -997,7 +884,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.tbz(smi_reg, 0, branch_imm); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM64 diff --git a/deps/v8/src/ic/arm64/ic-compiler-arm64.cc b/deps/v8/src/ic/arm64/ic-compiler-arm64.cc index 08ce4cba21..f9eab7d9d2 100644 --- a/deps/v8/src/ic/arm64/ic-compiler-arm64.cc +++ b/deps/v8/src/ic/arm64/ic-compiler-arm64.cc @@ -132,7 +132,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM64 diff --git a/deps/v8/src/ic/arm64/stub-cache-arm64.cc b/deps/v8/src/ic/arm64/stub-cache-arm64.cc index a9c56a31e7..ba5cbddb64 100644 --- a/deps/v8/src/ic/arm64/stub-cache-arm64.cc +++ b/deps/v8/src/ic/arm64/stub-cache-arm64.cc @@ -116,8 +116,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // extra3 don't conflict with the vector and slot registers, which need // to be preserved for a handler call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); } #endif @@ -157,7 +157,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, extra3); } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM64 diff --git a/deps/v8/src/ic/call-optimization.cc b/deps/v8/src/ic/call-optimization.cc index 85dc01acf0..31f5437228 100644 --- a/deps/v8/src/ic/call-optimization.cc +++ b/deps/v8/src/ic/call-optimization.cc @@ -111,5 +111,5 @@ void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) { is_simple_api_call_ = true; } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/handler-compiler.cc b/deps/v8/src/ic/handler-compiler.cc index c434ce515e..26d195326f 100644 --- a/deps/v8/src/ic/handler-compiler.cc +++ b/deps/v8/src/ic/handler-compiler.cc @@ -53,6 +53,16 @@ Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( while (true) { if (current_map->is_dictionary_map()) cache_name = name; if (current_map->prototype()->IsNull()) break; + if (name->IsPrivate()) { + // TODO(verwaest): Use nonexistent_private_symbol. + cache_name = name; + JSReceiver* prototype = JSReceiver::cast(current_map->prototype()); + if (!prototype->map()->is_hidden_prototype() && + !prototype->map()->IsGlobalObjectMap()) { + break; + } + } + last = handle(JSObject::cast(current_map->prototype())); current_map = handle(last->map()); } @@ -428,8 +438,11 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( if (is_nonexistent) { // Find the top object. Handle<JSObject> last; + PrototypeIterator::WhereToEnd end = + name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN + : PrototypeIterator::END_AT_NULL; PrototypeIterator iter(isolate(), holder()); - while (!iter.IsAtEnd()) { + while (!iter.IsAtEnd(end)) { last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); iter.Advance(); } @@ -524,7 +537,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( void ElementHandlerCompiler::CompileElementHandlers( - MapHandleList* receiver_maps, CodeHandleList* handlers) { + MapHandleList* receiver_maps, CodeHandleList* handlers, + LanguageMode language_mode) { for (int i = 0; i < receiver_maps->length(); ++i) { Handle<Map> receiver_map = receiver_maps->at(i); Handle<Code> cached_stub; @@ -532,7 +546,9 @@ void ElementHandlerCompiler::CompileElementHandlers( if (receiver_map->IsStringMap()) { cached_stub = LoadIndexedStringStub(isolate()).GetCode(); } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { - cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); + cached_stub = is_strong(language_mode) + ? isolate()->builtins()->KeyedLoadIC_Slow_Strong() + : isolate()->builtins()->KeyedLoadIC_Slow(); } else { bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; ElementsKind elements_kind = receiver_map->elements_kind(); @@ -540,8 +556,10 @@ void ElementHandlerCompiler::CompileElementHandlers( // No need to check for an elements-free prototype chain here, the // generated stub code needs to check that dynamically anyway. bool convert_hole_to_undefined = - is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && - *receiver_map == isolate()->get_initial_js_array_map(elements_kind); + (is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && + *receiver_map == + isolate()->get_initial_js_array_map(elements_kind)) && + !is_strong(language_mode); if (receiver_map->has_indexed_interceptor()) { cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode(); @@ -554,12 +572,15 @@ void ElementHandlerCompiler::CompileElementHandlers( convert_hole_to_undefined).GetCode(); } else { DCHECK(elements_kind == DICTIONARY_ELEMENTS); - cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); + LoadICState state = + LoadICState(is_strong(language_mode) ? LoadICState::kStrongModeState + : kNoExtraICState); + cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode(); } } handlers->Add(cached_stub); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/handler-compiler.h b/deps/v8/src/ic/handler-compiler.h index 077db92307..99bf5e6a7a 100644 --- a/deps/v8/src/ic/handler-compiler.h +++ b/deps/v8/src/ic/handler-compiler.h @@ -290,7 +290,8 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler { virtual ~ElementHandlerCompiler() {} void CompileElementHandlers(MapHandleList* receiver_maps, - CodeHandleList* handlers); + CodeHandleList* handlers, + LanguageMode language_mode); static void GenerateStoreSlow(MacroAssembler* masm); }; diff --git a/deps/v8/src/ic/ia32/access-compiler-ia32.cc b/deps/v8/src/ic/ia32/access-compiler-ia32.cc index 9bcbef0b6f..422a0be5f0 100644 --- a/deps/v8/src/ic/ia32/access-compiler-ia32.cc +++ b/deps/v8/src/ic/ia32/access-compiler-ia32.cc @@ -38,7 +38,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { } #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/ia32/handler-compiler-ia32.cc b/deps/v8/src/ic/ia32/handler-compiler-ia32.cc index 8a7c2bdb87..8f5200aee6 100644 --- a/deps/v8/src/ic/ia32/handler-compiler-ia32.cc +++ b/deps/v8/src/ic/ia32/handler-compiler-ia32.cc @@ -130,10 +130,9 @@ void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( MacroAssembler* masm, Register receiver, Register scratch1, Register scratch2, Label* miss_label) { - DCHECK(!FLAG_vector_ics); - __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); - __ mov(eax, scratch1); - __ ret(0); + // TODO(mvstanton): This isn't used on ia32. Move all the other + // platform implementations into a code stub so this method can be removed. + UNREACHABLE(); } @@ -809,7 +808,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/ia32/ic-compiler-ia32.cc b/deps/v8/src/ic/ia32/ic-compiler-ia32.cc index 6788bc7a88..abeacc86d4 100644 --- a/deps/v8/src/ic/ia32/ic-compiler-ia32.cc +++ b/deps/v8/src/ic/ia32/ic-compiler-ia32.cc @@ -128,7 +128,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/ia32/ic-ia32.cc b/deps/v8/src/ic/ia32/ic-ia32.cc index 54fd053eaf..d59e58521a 100644 --- a/deps/v8/src/ic/ia32/ic-ia32.cc +++ b/deps/v8/src/ic/ia32/ic-ia32.cc @@ -172,7 +172,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register scratch, Register scratch2, Register result, - Label* slow) { + Label* slow, LanguageMode language_mode) { // Register use: // receiver - holds the receiver and is unchanged. // key - holds the key and is unchanged (must be a smi). @@ -182,7 +182,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // 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; + Label done, in_bounds, absent; __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(scratch); @@ -200,7 +200,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ cmp(scratch2, masm->isolate()->factory()->null_value()); - __ j(equal, &return_undefined); + __ j(equal, &absent); __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset)); __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset)); // scratch: elements of current prototype @@ -215,9 +215,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ j(not_equal, slow); __ jmp(&check_next_prototype); - __ bind(&return_undefined); - __ mov(result, masm->isolate()->factory()->undefined_value()); - __ jmp(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ jmp(slow); + } else { + __ mov(result, masm->isolate()->factory()->undefined_value()); + __ jmp(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -263,74 +268,8 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -static Operand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Label* unmapped_case, Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - Factory* factory = masm->isolate()->factory(); - - // Check that the receiver is a JSObject. Because of the elements - // map check later, we do not need to check for interceptors or - // whether it requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); - __ j(below, slow_case); - - // Check that the key is a positive smi. - __ test(key, Immediate(0x80000001)); - __ j(not_zero, slow_case); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); - __ sub(scratch2, Immediate(Smi::FromInt(2))); - __ cmp(key, scratch2); - __ j(above_equal, unmapped_case); - - // Load element index and check whether it is the hole. - const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; - __ mov(scratch2, - FieldOperand(scratch1, key, times_half_pointer_size, kHeaderSize)); - __ cmp(scratch2, factory->the_hole_value()); - __ j(equal, unmapped_case); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - const int kContextOffset = FixedArray::kHeaderSize; - __ mov(scratch1, FieldOperand(scratch1, kContextOffset)); - return FieldOperand(scratch1, scratch2, times_half_pointer_size, - Context::kHeaderSize); -} - - -static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); - __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); - __ cmp(key, scratch); - __ j(greater_equal, slow_case); - return FieldOperand(backing_store, key, times_half_pointer_size, - FixedArray::kHeaderSize); -} - - -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is on the stack. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -352,7 +291,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // 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); + GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow, + language_mode); Isolate* isolate = masm->isolate(); Counters* counters = isolate->counters(); __ IncrementCounter(counters->keyed_load_generic_smi(), 1); @@ -384,7 +324,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); // Slow case: jump to runtime. __ IncrementCounter(counters->keyed_load_generic_slow(), 1); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); @@ -399,26 +339,21 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { Immediate(isolate->factory()->hash_table_map())); __ j(equal, &probe_dictionary); - 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)); - } + // 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)); 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); - if (FLAG_vector_ics) { - __ pop(VectorLoadICDescriptor::VectorRegister()); - __ pop(VectorLoadICDescriptor::SlotRegister()); - } + __ pop(LoadWithVectorDescriptor::VectorRegister()); + __ pop(LoadDescriptor::SlotRegister()); // Cache miss. GenerateMiss(masm); @@ -442,37 +377,6 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { } -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - // Return address is on the stack. - Label slow, notin; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(receiver.is(edx)); - DCHECK(name.is(ecx)); - DCHECK(value.is(eax)); - - Operand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, name, ebx, edi, ¬in, &slow); - __ mov(mapped_location, value); - __ lea(ecx, mapped_location); - __ mov(edx, value); - __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs); - __ Ret(); - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in ebx. - Operand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow); - __ mov(unmapped_location, value); - __ lea(edi, unmapped_location); - __ mov(edx, value); - __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); - __ Ret(); - __ bind(&slow); - GenerateMiss(masm); -} - - static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { @@ -656,10 +560,28 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(ebx, &slow); + + + if (FLAG_vector_stores) { + // 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( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ push(Immediate(Smi::FromInt(slot))); + __ push(Immediate(dummy_vector)); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( masm, Code::STORE_IC, flags, false, receiver, key, ebx, no_reg); + + if (FLAG_vector_stores) { + __ pop(VectorStoreICDescriptor::VectorRegister()); + __ pop(VectorStoreICDescriptor::SlotRegister()); + } + // Cache miss. __ jmp(&miss); @@ -711,7 +633,7 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = eax; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -726,33 +648,25 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); - DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && - !edi.is(vector)); - - __ pop(edi); - __ push(receiver); - __ push(name); - __ push(slot); - __ push(vector); - __ push(edi); - } else { - DCHECK(!ebx.is(receiver) && !ebx.is(name)); - __ pop(ebx); - __ push(receiver); - __ push(name); - __ push(ebx); - } + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && + !edi.is(vector)); + + __ pop(edi); + __ push(receiver); + __ push(name); + __ push(slot); + __ push(vector); + __ push(edi); } @@ -764,12 +678,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // Return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); @@ -780,8 +695,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ push(name); __ push(ebx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -794,12 +711,13 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // Return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); @@ -810,8 +728,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ push(name); __ push(ebx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } @@ -962,7 +882,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/ia32/stub-cache-ia32.cc b/deps/v8/src/ic/ia32/stub-cache-ia32.cc index cb560f12d7..aa807a77a6 100644 --- a/deps/v8/src/ic/ia32/stub-cache-ia32.cc +++ b/deps/v8/src/ic/ia32/stub-cache-ia32.cc @@ -61,8 +61,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, if (IC::ICUseVector(ic_kind)) { // The vector and slot were pushed onto the stack before starting the // probe, and need to be dropped before calling the handler. - __ pop(VectorLoadICDescriptor::VectorRegister()); - __ pop(VectorLoadICDescriptor::SlotRegister()); + __ pop(LoadWithVectorDescriptor::VectorRegister()); + __ pop(LoadDescriptor::SlotRegister()); } if (leave_frame) __ leave(); @@ -112,8 +112,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, if (IC::ICUseVector(ic_kind)) { // The vector and slot were pushed onto the stack before starting the // probe, and need to be dropped before calling the handler. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); DCHECK(!offset.is(vector) && !offset.is(slot)); __ pop(vector); @@ -204,7 +204,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_IA32 diff --git a/deps/v8/src/ic/ic-compiler.cc b/deps/v8/src/ic/ic-compiler.cc index dfee0127c6..a5ae6cfff4 100644 --- a/deps/v8/src/ic/ic-compiler.cc +++ b/deps/v8/src/ic/ic-compiler.cc @@ -52,6 +52,7 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic( ExtraICState extra_ic_state) { Isolate* isolate = name->GetIsolate(); if (handler.is_identical_to(isolate->builtins()->LoadIC_Normal()) || + handler.is_identical_to(isolate->builtins()->LoadIC_Normal_Strong()) || handler.is_identical_to(isolate->builtins()->StoreIC_Normal())) { name = isolate->factory()->normal_ic_symbol(); } @@ -87,28 +88,8 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic( } -Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( - Handle<Map> receiver_map) { - Isolate* isolate = receiver_map->GetIsolate(); - DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); - Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); - Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); - - Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); - if (probe->IsCode()) return Handle<Code>::cast(probe); - - Handle<Code> stub = ComputeKeyedLoadMonomorphicHandler(receiver_map); - PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); - Handle<Code> code = compiler.CompileMonomorphic( - receiver_map, stub, isolate->factory()->empty_string(), ELEMENT); - - Map::UpdateCodeCache(receiver_map, name, code); - return code; -} - - Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( - Handle<Map> receiver_map) { + Handle<Map> receiver_map, ExtraICState extra_ic_state) { Isolate* isolate = receiver_map->GetIsolate(); bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; ElementsKind elements_kind = receiver_map->elements_kind(); @@ -117,8 +98,8 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( // stub code needs to check that dynamically anyway. bool convert_hole_to_undefined = is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && - *receiver_map == isolate->get_initial_js_array_map(elements_kind); - + *receiver_map == isolate->get_initial_js_array_map(elements_kind) && + !(is_strong(LoadICState::GetLanguageMode(extra_ic_state))); Handle<Code> stub; if (receiver_map->has_indexed_interceptor()) { stub = LoadIndexedInterceptorStub(isolate).GetCode(); @@ -133,7 +114,8 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( stub = LoadFastElementStub(isolate, is_js_array, elements_kind, convert_hole_to_undefined).GetCode(); } else { - stub = LoadDictionaryElementStub(isolate).GetCode(); + stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state)) + .GetCode(); } return stub; } @@ -189,31 +171,6 @@ static void FillCache(Isolate* isolate, Handle<Code> code) { } -Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, - InlineCacheState ic_state, - ExtraICState extra_state) { - Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); - Handle<UnseededNumberDictionary> cache = - isolate->factory()->non_monomorphic_cache(); - int entry = cache->FindEntry(isolate, flags); - if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); - - PropertyICCompiler compiler(isolate, Code::LOAD_IC); - Handle<Code> code; - if (ic_state == UNINITIALIZED) { - code = compiler.CompileLoadInitialize(flags); - } else if (ic_state == PREMONOMORPHIC) { - code = compiler.CompileLoadPreMonomorphic(flags); - } else if (ic_state == MEGAMORPHIC) { - code = compiler.CompileLoadMegamorphic(flags); - } else { - UNREACHABLE(); - } - FillCache(isolate, code); - return code; -} - - Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate, InlineCacheState ic_state, ExtraICState extra_state) { @@ -266,7 +223,7 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map, Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic( - MapHandleList* receiver_maps) { + MapHandleList* receiver_maps, LanguageMode language_mode) { Isolate* isolate = receiver_maps->at(0)->GetIsolate(); DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); @@ -277,7 +234,7 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic( CodeHandleList handlers(receiver_maps->length()); ElementHandlerCompiler compiler(isolate); - compiler.CompileElementHandlers(receiver_maps, &handlers); + compiler.CompileElementHandlers(receiver_maps, &handlers, language_mode); PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); Handle<Code> code = ic_compiler.CompilePolymorphic( receiver_maps, &handlers, isolate->factory()->empty_string(), @@ -334,23 +291,6 @@ Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { } -Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { - LoadIC::GeneratePreMonomorphic(masm()); - Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); - PROFILE(isolate(), - CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); - return code; -} - - -Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { - MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state_)); - auto code = stub.GetCode(); - PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); - return code; -} - - Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { StoreIC::GenerateInitialize(masm()); Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); @@ -370,7 +310,7 @@ Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); - LanguageMode language_mode = StoreIC::GetLanguageMode(extra_state); + LanguageMode language_mode = StoreICState::GetLanguageMode(extra_state); GenerateRuntimeSetProperty(masm(), language_mode); Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); @@ -409,7 +349,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( Handle<Map> receiver_map(receiver_maps->at(i)); Handle<Code> cached_stub; Handle<Map> transitioned_map = - receiver_map->FindTransitionedMap(receiver_maps); + Map::FindTransitionedMap(receiver_map, receiver_maps); // TODO(mvstanton): The code below is doing pessimistic elements // transitions. I would like to stop doing that and rely on Allocation Site @@ -426,9 +366,11 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); } else { - if (receiver_map->has_fast_elements() || - receiver_map->has_external_array_elements() || - receiver_map->has_fixed_typed_array_elements()) { + if (IsSloppyArgumentsElements(elements_kind)) { + cached_stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode(); + } else if (receiver_map->has_fast_elements() || + receiver_map->has_external_array_elements() || + receiver_map->has_fixed_typed_array_elements()) { cached_stub = StoreFastElementStub(isolate(), is_js_array, elements_kind, store_mode).GetCode(); } else { @@ -456,9 +398,11 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( ElementsKind elements_kind = receiver_map->elements_kind(); bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; Handle<Code> stub; - if (receiver_map->has_fast_elements() || - receiver_map->has_external_array_elements() || - receiver_map->has_fixed_typed_array_elements()) { + if (receiver_map->has_sloppy_arguments_elements()) { + stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode(); + } else if (receiver_map->has_fast_elements() || + receiver_map->has_external_array_elements() || + receiver_map->has_fixed_typed_array_elements()) { stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind, store_mode).GetCode(); } else { @@ -477,5 +421,5 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/ic-compiler.h b/deps/v8/src/ic/ic-compiler.h index a6c4e81ab6..b5226e9a6e 100644 --- a/deps/v8/src/ic/ic-compiler.h +++ b/deps/v8/src/ic/ic-compiler.h @@ -18,8 +18,6 @@ class PropertyICCompiler : public PropertyAccessCompiler { ExtraICState extra_ic_state); // Named - static Handle<Code> ComputeLoad(Isolate* isolate, InlineCacheState ic_state, - ExtraICState extra_state); static Handle<Code> ComputeStore(Isolate* isolate, InlineCacheState ic_state, ExtraICState extra_state); @@ -34,13 +32,13 @@ class PropertyICCompiler : public PropertyAccessCompiler { // Keyed static Handle<Code> ComputeKeyedLoadMonomorphicHandler( - Handle<Map> receiver_map); - static Handle<Code> ComputeKeyedLoadMonomorphic(Handle<Map> receiver_map); + Handle<Map> receiver_map, ExtraICState extra_ic_state); static Handle<Code> ComputeKeyedStoreMonomorphic( Handle<Map> receiver_map, LanguageMode language_mode, KeyedAccessStoreMode store_mode); - static Handle<Code> ComputeKeyedLoadPolymorphic(MapHandleList* receiver_maps); + static Handle<Code> ComputeKeyedLoadPolymorphic(MapHandleList* receiver_maps, + LanguageMode language_mode); static Handle<Code> ComputeKeyedStorePolymorphic( MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, LanguageMode language_mode); @@ -69,8 +67,6 @@ class PropertyICCompiler : public PropertyAccessCompiler { CacheHolderFlag cache_holder = kCacheOnReceiver); Handle<Code> CompileLoadInitialize(Code::Flags flags); - Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags); - Handle<Code> CompileLoadMegamorphic(Code::Flags flags); Handle<Code> CompileStoreInitialize(Code::Flags flags); Handle<Code> CompileStorePreMonomorphic(Code::Flags flags); Handle<Code> CompileStoreGeneric(Code::Flags flags); diff --git a/deps/v8/src/ic/ic-inl.h b/deps/v8/src/ic/ic-inl.h index 45dd3476cf..b6ee6b13e5 100644 --- a/deps/v8/src/ic/ic-inl.h +++ b/deps/v8/src/ic/ic-inl.h @@ -48,41 +48,40 @@ Address IC::address() const { } -ConstantPoolArray* IC::constant_pool() const { - if (!FLAG_enable_ool_constant_pool) { +Address IC::constant_pool() const { + if (!FLAG_enable_embedded_constant_pool) { return NULL; } else { - Handle<ConstantPoolArray> result = raw_constant_pool_; + Address constant_pool = raw_constant_pool(); Debug* debug = isolate()->debug(); // First check if any break points are active if not just return the // original constant pool. - if (!debug->has_break_points()) return *result; + if (!debug->has_break_points()) return constant_pool; // At least one break point is active perform additional test to ensure that // break point locations are updated correctly. Address target = Assembler::target_address_from_return_address(pc()); if (debug->IsDebugBreak( - Assembler::target_address_at(target, raw_constant_pool()))) { + Assembler::target_address_at(target, constant_pool))) { // If the call site is a call to debug break then we want to return the // constant pool for the original code instead of the breakpointed code. return GetOriginalCode()->constant_pool(); } - return *result; + return constant_pool; } } -ConstantPoolArray* IC::raw_constant_pool() const { - if (FLAG_enable_ool_constant_pool) { - return *raw_constant_pool_; +Address IC::raw_constant_pool() const { + if (FLAG_enable_embedded_constant_pool) { + return *constant_pool_address_; } else { return NULL; } } -Code* IC::GetTargetAtAddress(Address address, - ConstantPoolArray* constant_pool) { +Code* IC::GetTargetAtAddress(Address address, Address constant_pool) { // Get the target address of the IC. Address target = Assembler::target_address_at(address, constant_pool); // Convert target address to the code object. Code::GetCodeFromTargetAddress @@ -94,13 +93,16 @@ Code* IC::GetTargetAtAddress(Address address, void IC::SetTargetAtAddress(Address address, Code* target, - ConstantPoolArray* constant_pool) { + Address constant_pool) { + if (AddressIsDeoptimizedCode(target->GetIsolate(), address)) return; + DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub()); - // Don't use this for load_ics when --vector-ics is turned on. - DCHECK(!(FLAG_vector_ics && target->is_inline_cache_stub()) || + DCHECK(!target->is_inline_cache_stub() || (target->kind() != Code::LOAD_IC && - target->kind() != Code::KEYED_LOAD_IC)); + target->kind() != Code::KEYED_LOAD_IC && + (!FLAG_vector_stores || (target->kind() != Code::STORE_IC && + target->kind() != Code::KEYED_STORE_IC)))); Heap* heap = target->GetHeap(); Code* old_target = GetTargetAtAddress(address, constant_pool); @@ -109,8 +111,8 @@ void IC::SetTargetAtAddress(Address address, Code* target, // ICs as language mode. The language mode of the IC must be preserved. if (old_target->kind() == Code::STORE_IC || old_target->kind() == Code::KEYED_STORE_IC) { - DCHECK(StoreIC::GetLanguageMode(old_target->extra_ic_state()) == - StoreIC::GetLanguageMode(target->extra_ic_state())); + DCHECK(StoreICState::GetLanguageMode(old_target->extra_ic_state()) == + StoreICState::GetLanguageMode(target->extra_ic_state())); } #endif Assembler::set_target_address_at(address, constant_pool, @@ -134,6 +136,9 @@ void LoadIC::set_target(Code* code) { // The contextual mode must be preserved across IC patching. DCHECK(LoadICState::GetContextualMode(code->extra_ic_state()) == LoadICState::GetContextualMode(target()->extra_ic_state())); + // Strongness must be preserved across IC patching. + DCHECK(LoadICState::GetLanguageMode(code->extra_ic_state()) == + LoadICState::GetLanguageMode(target()->extra_ic_state())); IC::set_target(code); } @@ -141,15 +146,16 @@ void LoadIC::set_target(Code* code) { void StoreIC::set_target(Code* code) { // Language mode must be preserved across IC patching. - DCHECK(GetLanguageMode(code->extra_ic_state()) == - GetLanguageMode(target()->extra_ic_state())); + DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == + StoreICState::GetLanguageMode(target()->extra_ic_state())); IC::set_target(code); } void KeyedStoreIC::set_target(Code* code) { // Language mode must be preserved across IC patching. - DCHECK(GetLanguageMode(code->extra_ic_state()) == language_mode()); + DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == + language_mode()); IC::set_target(code); } @@ -211,12 +217,25 @@ Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate, } -inline Code* IC::get_host() { +Code* IC::get_host() { return isolate() ->inner_pointer_to_code_cache() ->GetCacheEntry(address()) ->code; } + + +bool IC::AddressIsDeoptimizedCode() const { + return AddressIsDeoptimizedCode(isolate(), address()); +} + + +bool IC::AddressIsDeoptimizedCode(Isolate* isolate, Address address) { + Code* host = + isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; + return (host->kind() == Code::OPTIMIZED_FUNCTION && + host->marked_for_deoptimization()); +} } } // namespace v8::internal diff --git a/deps/v8/src/ic/ic-state.cc b/deps/v8/src/ic/ic-state.cc index 0c71949d8a..8ab08bc08d 100644 --- a/deps/v8/src/ic/ic-state.cc +++ b/deps/v8/src/ic/ic-state.cc @@ -12,7 +12,7 @@ namespace internal { // static void ICUtility::Clear(Isolate* isolate, Address address, - ConstantPoolArray* constant_pool) { + Address constant_pool) { IC::Clear(isolate, address, constant_pool); } @@ -52,7 +52,7 @@ BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state) isolate_(isolate) { op_ = static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state)); - strong_ = StrongField::decode(extra_ic_state); + strong_ = StrengthField::decode(extra_ic_state); left_kind_ = LeftKindField::decode(extra_ic_state); right_kind_ = fixed_right_arg_.IsJust() ? (Smi::IsValid(fixed_right_arg_.FromJust()) ? SMI : INT32) @@ -66,8 +66,7 @@ BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state) ExtraICState BinaryOpICState::GetExtraICState() const { ExtraICState extra_ic_state = OpField::encode(op_ - FIRST_TOKEN) | LeftKindField::encode(left_kind_) | - ResultKindField::encode(result_kind_) | - StrongField::encode(strong_) | + ResultKindField::encode(result_kind_) | StrengthField::encode(strong_) | HasFixedRightArgField::encode(fixed_right_arg_.IsJust()); if (fixed_right_arg_.IsJust()) { extra_ic_state = FixedRightArgValueField::update( @@ -86,14 +85,14 @@ void BinaryOpICState::GenerateAheadOfTime( // expensive at runtime. When solved we should be able to add most binops to // the snapshot instead of hand-picking them. // Generated list of commonly used stubs -#define GENERATE(op, left_kind, right_kind, result_kind) \ - do { \ - BinaryOpICState state(isolate, op, LanguageMode::SLOPPY); \ - state.left_kind_ = left_kind; \ - state.fixed_right_arg_ = Nothing<int>(); \ - state.right_kind_ = right_kind; \ - state.result_kind_ = result_kind; \ - Generate(isolate, state); \ +#define GENERATE(op, left_kind, right_kind, result_kind) \ + do { \ + BinaryOpICState state(isolate, op, Strength::WEAK); \ + state.left_kind_ = left_kind; \ + state.fixed_right_arg_ = Nothing<int>(); \ + state.right_kind_ = right_kind; \ + state.result_kind_ = result_kind; \ + Generate(isolate, state); \ } while (false) GENERATE(Token::ADD, INT32, INT32, INT32); GENERATE(Token::ADD, INT32, INT32, NUMBER); @@ -190,7 +189,7 @@ void BinaryOpICState::GenerateAheadOfTime( #undef GENERATE #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind) \ do { \ - BinaryOpICState state(isolate, op, LanguageMode::SLOPPY); \ + BinaryOpICState state(isolate, op, Strength::WEAK); \ state.left_kind_ = left_kind; \ state.fixed_right_arg_ = Just(fixed_right_arg_value); \ state.right_kind_ = SMI; \ @@ -224,6 +223,7 @@ Type* BinaryOpICState::GetResultType(Zone* zone) const { std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s) { os << "(" << Token::Name(s.op_); if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos"; + if (is_strong(s.strength())) os << "_Strong"; os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*"; if (s.fixed_right_arg_.IsJust()) { os << s.fixed_right_arg_.FromJust(); @@ -511,5 +511,5 @@ CompareICState::State CompareICState::TargetState( UNREACHABLE(); return GENERIC; // Make the compiler happy. } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/ic-state.h b/deps/v8/src/ic/ic-state.h index 76c0155206..e1fed19133 100644 --- a/deps/v8/src/ic/ic-state.h +++ b/deps/v8/src/ic/ic-state.h @@ -17,8 +17,7 @@ const int kMaxKeyedPolymorphism = 4; class ICUtility : public AllStatic { public: // Clear the inline cache to initial state. - static void Clear(Isolate* isolate, Address address, - ConstantPoolArray* constant_pool); + static void Clear(Isolate* isolate, Address address, Address constant_pool); }; @@ -57,9 +56,9 @@ std::ostream& operator<<(std::ostream& os, const CallICState& s); class BinaryOpICState final BASE_EMBEDDED { public: BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state); - BinaryOpICState(Isolate* isolate, Token::Value op, LanguageMode language_mode) + BinaryOpICState(Isolate* isolate, Token::Value op, Strength strength) : op_(op), - strong_(is_strong(language_mode)), + strong_(is_strong(strength)), left_kind_(NONE), right_kind_(NONE), result_kind_(NONE), @@ -106,8 +105,8 @@ class BinaryOpICState final BASE_EMBEDDED { return Max(left_kind_, right_kind_) == GENERIC; } - LanguageMode language_mode() const { - return strong_ ? LanguageMode::STRONG : LanguageMode::SLOPPY; + Strength strength() const { + return strong_ ? Strength::STRONG : Strength::WEAK; } // Returns true if the IC should enable the inline smi code (i.e. if either @@ -148,7 +147,7 @@ class BinaryOpICState final BASE_EMBEDDED { class OpField : public BitField<int, 0, 4> {}; class ResultKindField : public BitField<Kind, 4, 3> {}; class LeftKindField : public BitField<Kind, 7, 3> {}; - class StrongField : public BitField<bool, 10, 1> {}; + class StrengthField : public BitField<bool, 10, 1> {}; // When fixed right arg is set, we don't need to store the right kind. // Thus the two fields can overlap. class HasFixedRightArgField : public BitField<bool, 11, 1> {}; @@ -202,11 +201,24 @@ class CompareICState { class LoadICState final BASE_EMBEDDED { + private: + class ContextualModeBits : public BitField<ContextualMode, 0, 1> {}; + class LanguageModeBits + : public BitField<LanguageMode, ContextualModeBits::kNext, 2> {}; + STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); + const ExtraICState state_; + public: + static const uint32_t kNextBitFieldOffset = LanguageModeBits::kNext; + + static const ExtraICState kStrongModeState = STRONG + << LanguageModeBits::kShift; + explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} - explicit LoadICState(ContextualMode mode) - : state_(ContextualModeBits::encode(mode)) {} + explicit LoadICState(ContextualMode mode, LanguageMode language_mode) + : state_(ContextualModeBits::encode(mode) | + LanguageModeBits::encode(language_mode)) {} ExtraICState GetExtraICState() const { return state_; } @@ -214,14 +226,46 @@ class LoadICState final BASE_EMBEDDED { return ContextualModeBits::decode(state_); } + LanguageMode language_mode() const { + return LanguageModeBits::decode(state_); + } + static ContextualMode GetContextualMode(ExtraICState state) { return LoadICState(state).contextual_mode(); } - private: - class ContextualModeBits : public BitField<ContextualMode, 0, 1> {}; - STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); + static LanguageMode GetLanguageMode(ExtraICState state) { + return LoadICState(state).language_mode(); + } +}; + + +class StoreICState final BASE_EMBEDDED { + public: + explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} + explicit StoreICState(LanguageMode mode) + : state_(LanguageModeState::encode(mode)) {} + + ExtraICState GetExtraICState() const { return state_; } + + LanguageMode language_mode() const { + return LanguageModeState::decode(state_); + } + + static LanguageMode GetLanguageMode(ExtraICState state) { + return StoreICState(state).language_mode(); + } + + class LanguageModeState : public BitField<LanguageMode, 1, 2> {}; + STATIC_ASSERT(i::LANGUAGE_END == 3); + + // For convenience, a statically declared encoding of strict mode extra + // IC state. + static const ExtraICState kStrictModeState = STRICT + << LanguageModeState::kShift; + + private: const ExtraICState state_; }; } diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index 65b2e3df9a..9f75af8eb3 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -16,7 +16,7 @@ #include "src/ic/ic-inl.h" #include "src/ic/ic-compiler.h" #include "src/ic/stub-cache.h" -#include "src/messages.h" +#include "src/macro-assembler.h" #include "src/prototype.h" #include "src/runtime/runtime.h" @@ -90,6 +90,7 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { void IC::TraceIC(const char* type, Handle<Object> name) { if (FLAG_trace_ic) { + if (AddressIsDeoptimizedCode()) return; State new_state = UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state(); TraceIC(type, name, state(), new_state); @@ -150,10 +151,10 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, // levels of the stack frame iteration code. This yields a ~35% speedup when // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); - Address constant_pool = NULL; - if (FLAG_enable_ool_constant_pool) { - constant_pool = - Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); + Address* constant_pool = NULL; + if (FLAG_enable_embedded_constant_pool) { + constant_pool = reinterpret_cast<Address*>( + entry + ExitFrameConstants::kConstantPoolOffset); } Address* pc_address = reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); @@ -162,9 +163,9 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, // StubFailureTrampoline, we need to look one frame further down the stack to // find the frame pointer and the return address stack slot. if (depth == EXTRA_CALL_FRAME) { - if (FLAG_enable_ool_constant_pool) { - constant_pool = - Memory::Address_at(fp + StandardFrameConstants::kConstantPoolOffset); + if (FLAG_enable_embedded_constant_pool) { + constant_pool = reinterpret_cast<Address*>( + fp + StandardFrameConstants::kConstantPoolOffset); } const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); @@ -177,10 +178,8 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); #endif fp_ = fp; - if (FLAG_enable_ool_constant_pool) { - raw_constant_pool_ = handle( - ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), - isolate); + if (FLAG_enable_embedded_constant_pool) { + constant_pool_address_ = constant_pool; } pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); target_ = handle(raw_target(), isolate); @@ -231,14 +230,6 @@ bool IC::AddressIsOptimizedCode() const { } -bool IC::AddressIsDeoptimizedCode() const { - Code* host = - isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code; - return host->kind() == Code::OPTIMIZED_FUNCTION && - host->marked_for_deoptimization(); -} - - static void LookupForRead(LookupIterator* it) { for (; it->IsFound(); it->Next()) { switch (it->state()) { @@ -362,11 +353,10 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { } -MaybeHandle<Object> IC::TypeError(const char* type, Handle<Object> object, - Handle<Object> key) { +MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index, + Handle<Object> object, Handle<Object> key) { HandleScope scope(isolate()); - Handle<Object> args[2] = {key, object}; - THROW_NEW_ERROR(isolate(), NewTypeError(type, HandleVector(args, 2)), Object); + THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object); } @@ -488,8 +478,7 @@ void IC::PostPatching(Address address, Code* target, Code* old_target) { } -void IC::Clear(Isolate* isolate, Address address, - ConstantPoolArray* constant_pool) { +void IC::Clear(Isolate* isolate, Address address, Address constant_pool) { Code* target = GetTargetAtAddress(address, constant_pool); // Don't clear debug break inline cache as it will remove the break point. @@ -497,14 +486,13 @@ void IC::Clear(Isolate* isolate, Address address, switch (target->kind()) { case Code::LOAD_IC: - if (FLAG_vector_ics) return; - return LoadIC::Clear(isolate, address, target, constant_pool); case Code::KEYED_LOAD_IC: - if (FLAG_vector_ics) return; - return KeyedLoadIC::Clear(isolate, address, target, constant_pool); + return; case Code::STORE_IC: + if (FLAG_vector_stores) return; return StoreIC::Clear(isolate, address, target, constant_pool); case Code::KEYED_STORE_IC: + if (FLAG_vector_stores) return; return KeyedStoreIC::Clear(isolate, address, target, constant_pool); case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target, constant_pool); @@ -522,18 +510,6 @@ void IC::Clear(Isolate* isolate, Address address, } -void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool) { - DCHECK(!FLAG_vector_ics); - if (IsCleared(target)) return; - - // Make sure to also clear the map used in inline fast cases. If we - // do not clear these maps, cached code can keep objects alive - // through the embedded maps. - SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); -} - - void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { if (IsCleared(nexus)) return; // Make sure to also clear the map used in inline fast cases. If we @@ -558,16 +534,6 @@ void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { } -void LoadIC::Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool) { - DCHECK(!FLAG_vector_ics); - if (IsCleared(target)) return; - Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, - target->extra_ic_state()); - SetTargetAtAddress(address, code, constant_pool); -} - - void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { if (IsCleared(nexus)) return; State state = nexus->StateFromFeedback(); @@ -577,7 +543,7 @@ void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { void StoreIC::Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool) { + Address constant_pool) { if (IsCleared(target)) return; Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, target->extra_ic_state()); @@ -585,34 +551,54 @@ void StoreIC::Clear(Isolate* isolate, Address address, Code* target, } +void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { + if (IsCleared(nexus)) return; + State state = nexus->StateFromFeedback(); + nexus->ConfigurePremonomorphic(); + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); +} + + void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool) { + Address constant_pool) { if (IsCleared(target)) return; - SetTargetAtAddress( - address, *pre_monomorphic_stub( - isolate, StoreIC::GetLanguageMode(target->extra_ic_state())), - constant_pool); + Handle<Code> code = pre_monomorphic_stub( + isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); + SetTargetAtAddress(address, *code, constant_pool); +} + + +void KeyedStoreIC::Clear(Isolate* isolate, Code* host, + KeyedStoreICNexus* nexus) { + if (IsCleared(nexus)) return; + State state = nexus->StateFromFeedback(); + nexus->ConfigurePremonomorphic(); + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); } void CompareIC::Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool) { + Address constant_pool) { DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); CompareICStub stub(target->stub_key(), isolate); // Only clear CompareICs that can retain objects. if (stub.state() != CompareICState::KNOWN_OBJECT) return; - SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()), + SetTargetAtAddress(address, + GetRawUninitialized(isolate, stub.op(), stub.strength()), constant_pool); PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); } // static -Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate) { +Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate, + ExtraICState extra_state) { if (FLAG_compiled_keyed_generic_loads) { - return KeyedLoadGenericStub(isolate).GetCode(); + return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode(); } else { - return isolate->builtins()->KeyedLoadIC_Megamorphic(); + return is_strong(LoadICState::GetLanguageMode(extra_state)) + ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong() + : isolate->builtins()->KeyedLoadIC_Megamorphic(); } } @@ -628,24 +614,10 @@ static bool MigrateDeprecated(Handle<Object> object) { void IC::ConfigureVectorState(IC::State new_state) { DCHECK(UseVector()); - if (kind() == Code::LOAD_IC) { - LoadICNexus* nexus = casted_nexus<LoadICNexus>(); - if (new_state == PREMONOMORPHIC) { - nexus->ConfigurePremonomorphic(); - } else if (new_state == MEGAMORPHIC) { - nexus->ConfigureMegamorphic(); - } else { - UNREACHABLE(); - } - } else if (kind() == Code::KEYED_LOAD_IC) { - KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); - if (new_state == PREMONOMORPHIC) { - nexus->ConfigurePremonomorphic(); - } else if (new_state == MEGAMORPHIC) { - nexus->ConfigureMegamorphic(); - } else { - UNREACHABLE(); - } + if (new_state == PREMONOMORPHIC) { + nexus()->ConfigurePremonomorphic(); + } else if (new_state == MEGAMORPHIC) { + nexus()->ConfigureMegamorphic(); } else { UNREACHABLE(); } @@ -662,10 +634,16 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, if (kind() == Code::LOAD_IC) { LoadICNexus* nexus = casted_nexus<LoadICNexus>(); nexus->ConfigureMonomorphic(map, handler); - } else { - DCHECK(kind() == Code::KEYED_LOAD_IC); + } else if (kind() == Code::KEYED_LOAD_IC) { KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); nexus->ConfigureMonomorphic(name, map, handler); + } else if (kind() == Code::STORE_IC) { + StoreICNexus* nexus = casted_nexus<StoreICNexus>(); + nexus->ConfigureMonomorphic(map, handler); + } else { + DCHECK(kind() == Code::KEYED_STORE_IC); + KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); + nexus->ConfigureMonomorphic(name, map, handler); } vector_set_ = true; @@ -680,10 +658,16 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, if (kind() == Code::LOAD_IC) { LoadICNexus* nexus = casted_nexus<LoadICNexus>(); nexus->ConfigurePolymorphic(maps, handlers); - } else { - DCHECK(kind() == Code::KEYED_LOAD_IC); + } else if (kind() == Code::KEYED_LOAD_IC) { KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); nexus->ConfigurePolymorphic(name, maps, handlers); + } else if (kind() == Code::STORE_IC) { + StoreICNexus* nexus = casted_nexus<StoreICNexus>(); + nexus->ConfigurePolymorphic(maps, handlers); + } else { + DCHECK(kind() == Code::KEYED_STORE_IC); + KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); + nexus->ConfigurePolymorphic(name, maps, handlers); } vector_set_ = true; @@ -696,7 +680,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { // If the object is undefined or null it's illegal to try to get any // of its properties; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { - return TypeError("non_object_property_load", object, name); + return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); } // Check if the name is trivially convertible to an index and get @@ -705,18 +689,16 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { // Rewrite to the generic keyed load stub. if (FLAG_use_ic) { - if (UseVector()) { - ConfigureVectorState(MEGAMORPHIC); - } else { - set_target(*megamorphic_stub()); - } + DCHECK(UseVector()); + ConfigureVectorState(MEGAMORPHIC); TRACE_IC("LoadIC", name); TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); } Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), result, - Runtime::GetElementOrCharAt(isolate(), object, index), Object); + Runtime::GetElementOrCharAt(isolate(), object, index, language_mode()), + Object); return result; } @@ -759,8 +741,9 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { // Get the property. Handle<Object> result; - ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), - Object); + + ASSIGN_RETURN_ON_EXCEPTION( + isolate(), result, Object::GetProperty(&it, language_mode()), Object); if (it.IsFound()) { return result; } else if (!IsUndeclaredGlobal(object)) { @@ -942,90 +925,36 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) { Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ExtraICState extra_state) { - if (FLAG_vector_ics) { - return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); - } - - return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); -} - - -Handle<Code> LoadIC::load_global(Isolate* isolate, Handle<GlobalObject> global, - Handle<String> name) { - // This special IC doesn't work with vector ics. - DCHECK(!FLAG_vector_ics); - - Handle<ScriptContextTable> script_contexts( - global->native_context()->script_context_table()); - - ScriptContextTable::LookupResult lookup_result; - if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) { - return initialize_stub(isolate, LoadICState(CONTEXTUAL).GetExtraICState()); - } - - Handle<Map> global_map(global->map()); - Handle<Code> handler = PropertyHandlerCompiler::Find( - name, global_map, Code::LOAD_IC, kCacheOnReceiver, Code::NORMAL); - if (handler.is_null()) { - LookupIterator it(global, name); - if (!it.IsFound() || !it.GetHolder<JSObject>().is_identical_to(global) || - it.state() != LookupIterator::DATA) { - return initialize_stub(isolate, - LoadICState(CONTEXTUAL).GetExtraICState()); - } - NamedLoadHandlerCompiler compiler(isolate, global_map, global, - kCacheOnReceiver); - Handle<PropertyCell> cell = it.GetPropertyCell(); - handler = compiler.CompileLoadGlobal(cell, name, it.IsConfigurable()); - Map::UpdateCodeCache(global_map, name, handler); - } - return PropertyICCompiler::ComputeMonomorphic( - Code::LOAD_IC, name, handle(global->map()), handler, - LoadICState(CONTEXTUAL).GetExtraICState()); + return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); } Handle<Code> LoadIC::initialize_stub_in_optimized_code( Isolate* isolate, ExtraICState extra_state, State initialization_state) { - if (FLAG_vector_ics) { - return VectorRawLoadStub(isolate, LoadICState(extra_state)).GetCode(); - } - return PropertyICCompiler::ComputeLoad(isolate, initialization_state, - extra_state); + return LoadICStub(isolate, LoadICState(extra_state)).GetCode(); } -Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) { - if (FLAG_vector_ics) { - return KeyedLoadICTrampolineStub(isolate).GetCode(); - } - - return isolate->builtins()->KeyedLoadIC_Initialize(); +Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate, + ExtraICState extra_state) { + return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); } Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( - Isolate* isolate, State initialization_state) { - if (FLAG_vector_ics && initialization_state != MEGAMORPHIC) { - return VectorRawKeyedLoadStub(isolate).GetCode(); - } - switch (initialization_state) { - case UNINITIALIZED: - return isolate->builtins()->KeyedLoadIC_Initialize(); - case PREMONOMORPHIC: - return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); - case MEGAMORPHIC: - return isolate->builtins()->KeyedLoadIC_Megamorphic(); - default: - UNREACHABLE(); + Isolate* isolate, State initialization_state, ExtraICState extra_state) { + if (initialization_state != MEGAMORPHIC) { + return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); } - return Handle<Code>(); + return is_strong(LoadICState::GetLanguageMode(extra_state)) + ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong() + : isolate->builtins()->KeyedLoadIC_Megamorphic(); } -Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, - LanguageMode language_mode, - State initialization_state) { +static Handle<Code> KeyedStoreICInitializeStubHelper( + Isolate* isolate, LanguageMode language_mode, + InlineCacheState initialization_state) { switch (initialization_state) { case UNINITIALIZED: return is_strict(language_mode) @@ -1046,36 +975,34 @@ Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, } -Handle<Code> LoadIC::megamorphic_stub() { - if (kind() == Code::LOAD_IC) { - MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); +Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, + LanguageMode language_mode, + State initialization_state) { + if (FLAG_vector_stores) { + VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); return stub.GetCode(); - } else { - DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); - return KeyedLoadIC::ChooseMegamorphicStub(isolate()); } -} - -Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, - ExtraICState extra_state) { - DCHECK(!FLAG_vector_ics); - return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); + return KeyedStoreICInitializeStubHelper(isolate, language_mode, + initialization_state); } -Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { - return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); +Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( + Isolate* isolate, LanguageMode language_mode, State initialization_state) { + if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) { + VectorKeyedStoreICStub stub(isolate, StoreICState(language_mode)); + return stub.GetCode(); + } + + return KeyedStoreICInitializeStubHelper(isolate, language_mode, + initialization_state); } -Handle<Code> LoadIC::pre_monomorphic_stub() const { - if (kind() == Code::LOAD_IC) { - return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); - } else { - DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); - return KeyedLoadIC::pre_monomorphic_stub(isolate()); - } +Handle<Code> LoadIC::megamorphic_stub() { + DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); + return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state()); } @@ -1089,11 +1016,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { if (state() == UNINITIALIZED) { // This is the first time we execute this inline cache. Set the target to // the pre monomorphic stub to delay setting the monomorphic state. - if (UseVector()) { - ConfigureVectorState(PREMONOMORPHIC); - } else { - set_target(*pre_monomorphic_stub()); - } + ConfigureVectorState(PREMONOMORPHIC); TRACE_IC("LoadIC", lookup->name()); return; } @@ -1103,7 +1026,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { lookup->state() == LookupIterator::ACCESS_CHECK) { code = slow_stub(); } else if (!lookup->IsFound()) { - if (kind() == Code::LOAD_IC) { + if (kind() == Code::LOAD_IC && !is_strong(language_mode())) { code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), receiver_map()); // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. @@ -1334,7 +1257,9 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, // property must be found in the object for the stub to be // applicable. if (!receiver_is_holder) break; - return isolate()->builtins()->LoadIC_Normal(); + return is_strong(language_mode()) + ? isolate()->builtins()->LoadIC_Normal_Strong() + : isolate()->builtins()->LoadIC_Normal(); } // -------------- Fields -------------- @@ -1381,7 +1306,7 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { } else { int int_value = FastD2I(value); if (value == int_value && Smi::IsValid(int_value)) { - key = Handle<Smi>(Smi::FromInt(int_value), isolate); + key = handle(Smi::FromInt(int_value), isolate); } } } else if (key->IsUndefined()) { @@ -1399,13 +1324,11 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { if (target_receiver_maps.length() == 0) { - if (FLAG_vector_ics) { - Handle<Code> handler = - PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); - ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); - return null_handle; - } - return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); + Handle<Code> handler = + PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( + receiver_map, extra_ic_state()); + ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); + return null_handle; } // The first time a receiver is seen that is a transitioned version of the @@ -1419,13 +1342,11 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { IsMoreGeneralElementsKindTransition( target_receiver_maps.at(0)->elements_kind(), Handle<JSObject>::cast(receiver)->GetElementsKind())) { - if (FLAG_vector_ics) { - Handle<Code> handler = - PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); - ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); - return null_handle; - } - return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); + Handle<Code> handler = + PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( + receiver_map, extra_ic_state()); + ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); + return null_handle; } DCHECK(state() != GENERIC); @@ -1446,16 +1367,12 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { return megamorphic_stub(); } - if (FLAG_vector_ics) { - CodeHandleList handlers(target_receiver_maps.length()); - ElementHandlerCompiler compiler(isolate()); - compiler.CompileElementHandlers(&target_receiver_maps, &handlers); - ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, - &handlers); - return null_handle; - } - - return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); + CodeHandleList handlers(target_receiver_maps.length()); + ElementHandlerCompiler compiler(isolate()); + compiler.CompileElementHandlers(&target_receiver_maps, &handlers, + language_mode()); + ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers); + return null_handle; } @@ -1464,7 +1381,8 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, if (MigrateDeprecated(object)) { Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( - isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), + isolate(), result, + Runtime::GetObjectProperty(isolate(), object, key, language_mode()), Object); return result; } @@ -1489,33 +1407,24 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, } } - if (!UseVector()) { - if (!is_target_set()) { - Code* generic = *megamorphic_stub(); - if (*stub == generic) { - TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); - } - - set_target(*stub); - TRACE_IC("LoadIC", key); + DCHECK(UseVector()); + if (!is_vector_set() || stub.is_null()) { + Code* generic = *megamorphic_stub(); + if (!stub.is_null() && *stub == generic) { + ConfigureVectorState(MEGAMORPHIC); + TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); } - } else { - if (!is_vector_set() || stub.is_null()) { - Code* generic = *megamorphic_stub(); - if (!stub.is_null() && *stub == generic) { - ConfigureVectorState(MEGAMORPHIC); - TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); - } - TRACE_IC("LoadIC", key); - } + TRACE_IC("LoadIC", key); } if (!load_handle.is_null()) return load_handle; + Handle<Object> result; - ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, - Runtime::GetObjectProperty(isolate(), object, key), - Object); + ASSIGN_RETURN_ON_EXCEPTION( + isolate(), result, + Runtime::GetObjectProperty(isolate(), object, key, language_mode()), + Object); return result; } @@ -1596,7 +1505,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, Handle<Context> script_context = ScriptContextTable::GetContext( script_contexts, lookup_result.context_index); if (lookup_result.mode == CONST) { - return TypeError("const_assign", object, name); + return TypeError(MessageTemplate::kConstAssign, object, name); } Handle<Object> previous_value = @@ -1632,7 +1541,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, // If the object is undefined or null it's illegal to try to set any // properties on it; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { - return TypeError("non_object_property_store", object, name); + return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name); } // Check if the given name is an array index. @@ -1646,8 +1555,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), result, - JSObject::SetElement(receiver, index, value, NONE, language_mode()), - Object); + JSObject::SetElement(receiver, index, value, language_mode()), Object); return value; } @@ -1690,16 +1598,43 @@ Handle<Code> CallIC::initialize_stub_in_optimized_code( } +static Handle<Code> StoreICInitializeStubHelper( + Isolate* isolate, ExtraICState extra_state, + InlineCacheState initialization_state) { + Handle<Code> ic = PropertyICCompiler::ComputeStore( + isolate, initialization_state, extra_state); + return ic; +} + + Handle<Code> StoreIC::initialize_stub(Isolate* isolate, LanguageMode language_mode, State initialization_state) { DCHECK(initialization_state == UNINITIALIZED || initialization_state == PREMONOMORPHIC || initialization_state == MEGAMORPHIC); - ExtraICState extra_state = ComputeExtraICState(language_mode); - Handle<Code> ic = PropertyICCompiler::ComputeStore( - isolate, initialization_state, extra_state); - return ic; + if (FLAG_vector_stores) { + VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); + return stub.GetCode(); + } + + return StoreICInitializeStubHelper( + isolate, ComputeExtraICState(language_mode), initialization_state); +} + + +Handle<Code> StoreIC::initialize_stub_in_optimized_code( + Isolate* isolate, LanguageMode language_mode, State initialization_state) { + DCHECK(initialization_state == UNINITIALIZED || + initialization_state == PREMONOMORPHIC || + initialization_state == MEGAMORPHIC); + if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) { + VectorStoreICStub stub(isolate, StoreICState(language_mode)); + return stub.GetCode(); + } + + return StoreICInitializeStubHelper( + isolate, ComputeExtraICState(language_mode), initialization_state); } @@ -1740,7 +1675,11 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, if (state() == UNINITIALIZED) { // This is the first time we execute this inline cache. Set the target to // the pre monomorphic stub to delay setting the monomorphic state. - set_target(*pre_monomorphic_stub()); + if (FLAG_vector_stores) { + ConfigureVectorState(PREMONOMORPHIC); + } else { + set_target(*pre_monomorphic_stub()); + } TRACE_IC("StoreIC", lookup->name()); return; } @@ -1780,7 +1719,8 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, // This is currently guaranteed by checks in StoreIC::Store. Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); Handle<JSObject> holder = lookup->GetHolder<JSObject>(); - DCHECK(!receiver->IsAccessCheckNeeded()); + DCHECK(!receiver->IsAccessCheckNeeded() || + isolate()->IsInternallyUsedPropertyName(lookup->name())); switch (lookup->state()) { case LookupIterator::TRANSITION: { @@ -1826,6 +1766,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); break; } + if (AccessorInfo::cast(*accessors)->is_special_data_property() && + !lookup->HolderIsReceiverOrHiddenPrototype()) { + TRACE_GENERIC_IC(isolate(), "StoreIC", + "special data property in prototype chain"); + break; + } if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info, receiver_map())) { TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); @@ -2172,11 +2118,20 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, StoreIC::Store(object, Handle<Name>::cast(key), value, JSReceiver::MAY_BE_STORE_FROM_KEYED), Object); - if (!is_target_set()) { - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", - "unhandled internalized string key"); - TRACE_IC("StoreIC", key); - set_target(*stub); + if (FLAG_vector_stores) { + if (!is_vector_set()) { + ConfigureVectorState(MEGAMORPHIC); + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", + "unhandled internalized string key"); + TRACE_IC("StoreIC", key); + } + } else { + if (!is_target_set()) { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", + "unhandled internalized string key"); + TRACE_IC("StoreIC", key); + set_target(*stub); + } } return store_handle; } @@ -2203,14 +2158,10 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, Handle<JSObject> receiver = Handle<JSObject>::cast(object); bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); if (receiver->elements()->map() == - isolate()->heap()->sloppy_arguments_elements_map()) { - if (is_sloppy(language_mode())) { - stub = sloppy_arguments_stub(); - } else { - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); - } - } else if (key_is_smi_like && - !(target().is_identical_to(sloppy_arguments_stub()))) { + isolate()->heap()->sloppy_arguments_elements_map() && + !is_sloppy(language_mode())) { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); + } else if (key_is_smi_like) { // We should go generic if receiver isn't a dictionary, but our // prototype chain does have dictionary elements. This ensures that // other non-dictionary receivers in the polymorphic case benefit @@ -2237,17 +2188,28 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, Object); } - DCHECK(!is_target_set()); - Code* megamorphic = *megamorphic_stub(); - if (*stub == megamorphic) { - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); - } - if (*stub == *slow_stub()) { - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); - } - DCHECK(!stub.is_null()); - if (!AddressIsDeoptimizedCode()) { - set_target(*stub); + if (FLAG_vector_stores) { + if (!is_vector_set() || stub.is_null()) { + Code* megamorphic = *megamorphic_stub(); + if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { + ConfigureVectorState(MEGAMORPHIC); + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", + *stub == megamorphic ? "set generic" : "slow stub"); + } + } + } else { + DCHECK(!is_target_set()); + Code* megamorphic = *megamorphic_stub(); + if (*stub == megamorphic) { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); + } else if (*stub == *slow_stub()) { + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); + } + + DCHECK(!stub.is_null()); + if (!AddressIsDeoptimizedCode()) { + set_target(*stub); + } } TRACE_IC("StoreIC", key); @@ -2296,7 +2258,7 @@ void CallIC::PatchMegamorphic(Handle<Object> function) { // We are going generic. CallICNexus* nexus = casted_nexus<CallICNexus>(); - nexus->ConfigureGeneric(); + nexus->ConfigureMegamorphic(); // Vector-based ICs have a different calling convention in optimized code // than full code so the correct stub has to be chosen. @@ -2331,7 +2293,7 @@ void CallIC::HandleMiss(Handle<Object> function) { if (feedback->IsWeakCell() || !function->IsJSFunction()) { // We are going generic. - nexus->ConfigureGeneric(); + nexus->ConfigureMegamorphic(); } else { // The feedback is either uninitialized or an allocation site. // It might be an allocation site because if we re-compile the full code @@ -2408,31 +2370,22 @@ RUNTIME_FUNCTION(LoadIC_Miss) { Handle<Name> key = args.at<Name>(1); Handle<Object> result; - if (FLAG_vector_ics) { - DCHECK(args.length() == 4); - Handle<Smi> slot = args.at<Smi>(2); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); - // A monomorphic or polymorphic KeyedLoadIC with a string key can call the - // LoadIC miss handler if the handler misses. Since the vector Nexus is - // set up outside the IC, handle that here. - if (vector->GetKind(vector_slot) == Code::LOAD_IC) { - LoadICNexus nexus(vector, vector_slot); - LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, - ic.Load(receiver, key)); - } else { - DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); - KeyedLoadICNexus nexus(vector, vector_slot); - KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, - ic.Load(receiver, key)); - } + DCHECK(args.length() == 4); + Handle<Smi> slot = args.at<Smi>(2); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + // A monomorphic or polymorphic KeyedLoadIC with a string key can call the + // LoadIC miss handler if the handler misses. Since the vector Nexus is + // set up outside the IC, handle that here. + if (vector->GetKind(vector_slot) == Code::LOAD_IC) { + LoadICNexus nexus(vector, vector_slot); + LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); } else { - DCHECK(args.length() == 2); - LoadIC ic(IC::NO_EXTRA_FRAME, isolate); + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); + KeyedLoadICNexus nexus(vector, vector_slot); + KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); } @@ -2448,22 +2401,14 @@ RUNTIME_FUNCTION(KeyedLoadIC_Miss) { Handle<Object> key = args.at<Object>(1); Handle<Object> result; - if (FLAG_vector_ics) { - DCHECK(args.length() == 4); - Handle<Smi> slot = args.at<Smi>(2); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); - KeyedLoadICNexus nexus(vector, vector_slot); - KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); - } else { - DCHECK(args.length() == 2); - KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); - } - + DCHECK(args.length() == 4); + Handle<Smi> slot = args.at<Smi>(2); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + KeyedLoadICNexus nexus(vector, vector_slot); + KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); return *result; } @@ -2475,21 +2420,14 @@ RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { Handle<Object> key = args.at<Object>(1); Handle<Object> result; - if (FLAG_vector_ics) { - DCHECK(args.length() == 4); - Handle<Smi> slot = args.at<Smi>(2); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); - KeyedLoadICNexus nexus(vector, vector_slot); - KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); - } else { - DCHECK(args.length() == 2); - KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); - } + DCHECK(args.length() == 4); + Handle<Smi> slot = args.at<Smi>(2); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + KeyedLoadICNexus nexus(vector, vector_slot); + KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); return *result; } @@ -2499,14 +2437,37 @@ RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { RUNTIME_FUNCTION(StoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3); - StoreIC ic(IC::NO_EXTRA_FRAME, isolate); Handle<Object> receiver = args.at<Object>(0); Handle<Name> key = args.at<Name>(1); - ic.UpdateState(receiver, key); + Handle<Object> value = args.at<Object>(2); Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, ic.Store(receiver, key, args.at<Object>(2))); + + if (FLAG_vector_stores) { + DCHECK(args.length() == 5); + Handle<Smi> slot = args.at<Smi>(3); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + if (vector->GetKind(vector_slot) == Code::STORE_IC) { + StoreICNexus nexus(vector, vector_slot); + StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } else { + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC); + KeyedStoreICNexus nexus(vector, vector_slot); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } + } else { + DCHECK(args.length() == 3); + StoreIC ic(IC::NO_EXTRA_FRAME, isolate); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } return *result; } @@ -2514,14 +2475,37 @@ RUNTIME_FUNCTION(StoreIC_Miss) { RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3 || args.length() == 4); - StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); Handle<Object> receiver = args.at<Object>(0); Handle<Name> key = args.at<Name>(1); - ic.UpdateState(receiver, key); + Handle<Object> value = args.at<Object>(2); Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, ic.Store(receiver, key, args.at<Object>(2))); + + if (FLAG_vector_stores) { + DCHECK(args.length() == 5); + Handle<Smi> slot = args.at<Smi>(3); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + if (vector->GetKind(vector_slot) == Code::STORE_IC) { + StoreICNexus nexus(vector, vector_slot); + StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } else { + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC); + KeyedStoreICNexus nexus(vector, vector_slot); + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } + } else { + DCHECK(args.length() == 3 || args.length() == 4); + StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } return *result; } @@ -2530,14 +2514,28 @@ RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { RUNTIME_FUNCTION(KeyedStoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3); - KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); Handle<Object> receiver = args.at<Object>(0); Handle<Object> key = args.at<Object>(1); - ic.UpdateState(receiver, key); + Handle<Object> value = args.at<Object>(2); Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, ic.Store(receiver, key, args.at<Object>(2))); + + if (FLAG_vector_stores) { + DCHECK(args.length() == 5); + Handle<Smi> slot = args.at<Smi>(3); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + KeyedStoreICNexus nexus(vector, vector_slot); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } else { + DCHECK(args.length() == 3); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } return *result; } @@ -2545,14 +2543,28 @@ RUNTIME_FUNCTION(KeyedStoreIC_Miss) { RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3); - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); Handle<Object> receiver = args.at<Object>(0); Handle<Object> key = args.at<Object>(1); - ic.UpdateState(receiver, key); + Handle<Object> value = args.at<Object>(2); Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, ic.Store(receiver, key, args.at<Object>(2))); + + if (FLAG_vector_stores) { + DCHECK(args.length() == 5); + Handle<Smi> slot = args.at<Smi>(3); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + KeyedStoreICNexus nexus(vector, vector_slot); + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + ic.Store(receiver, key, value)); + } else { + DCHECK(args.length() == 3); + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, ic.Store(receiver, key, args.at<Object>(2))); + } return *result; } @@ -2618,7 +2630,7 @@ MaybeHandle<Object> BinaryOpIC::Transition( // Compute the actual result using the builtin for the binary operation. Object* builtin = isolate()->js_builtins_object()->javascript_builtin( - TokenToJSBuiltin(state.op(), state.language_mode())); + TokenToJSBuiltin(state.op(), state.strength())); Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( @@ -2718,8 +2730,9 @@ RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) { } -Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { - CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED, +Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op, + Strength strength) { + CompareICStub stub(isolate, op, strength, CompareICState::UNINITIALIZED, CompareICState::UNINITIALIZED, CompareICState::UNINITIALIZED); Code* code = NULL; @@ -2728,8 +2741,9 @@ Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { } -Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { - CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED, +Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op, + Strength strength) { + CompareICStub stub(isolate, op, strength, CompareICState::UNINITIALIZED, CompareICState::UNINITIALIZED, CompareICState::UNINITIALIZED); return stub.GetCode(); @@ -2746,7 +2760,8 @@ Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { CompareICState::State state = CompareICState::TargetState( old_stub.state(), old_stub.left(), old_stub.right(), op_, HasInlinedSmiCode(address()), x, y); - CompareICStub stub(isolate(), op_, new_left, new_right, state); + CompareICStub stub(isolate(), op_, old_stub.strength(), new_left, new_right, + state); if (state == CompareICState::KNOWN_OBJECT) { stub.set_known_map( Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); @@ -2786,8 +2801,7 @@ RUNTIME_FUNCTION(CompareIC_Miss) { } -void CompareNilIC::Clear(Address address, Code* target, - ConstantPoolArray* constant_pool) { +void CompareNilIC::Clear(Address address, Code* target, Address constant_pool) { if (IsCleared(target)) return; ExtraICState state = target->extra_ic_state(); @@ -2856,8 +2870,8 @@ RUNTIME_FUNCTION(Unreachable) { Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op, - LanguageMode language_mode) { - if (is_strong(language_mode)) { + Strength strength) { + if (is_strong(strength)) { switch (op) { default: UNREACHABLE(); case Token::ADD: return Builtins::ADD_STRONG; @@ -2956,10 +2970,12 @@ RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { Handle<JSObject> holder = args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); HandleScope scope(isolate); - auto res = JSObject::GetPropertyWithInterceptor(holder, receiver, name); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); + LookupIterator it(receiver, name, holder, LookupIterator::OWN); + bool done; Handle<Object> result; - if (res.ToHandle(&result)) return *result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, JSObject::GetPropertyWithInterceptor(&it, &done)); + if (done) return *result; return isolate->heap()->no_interceptor_result_sentinel(); } @@ -2996,6 +3012,7 @@ RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { Handle<Object> result; LookupIterator it(receiver, name, holder); + // TODO(conradw): Investigate strong mode semantics for this. ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::GetProperty(&it)); @@ -3035,14 +3052,17 @@ RUNTIME_FUNCTION(StorePropertyWithInterceptor) { RUNTIME_FUNCTION(LoadElementWithInterceptor) { + // TODO(verwaest): This should probably get the holder and receiver as input. HandleScope scope(isolate); Handle<JSObject> receiver = args.at<JSObject>(0); DCHECK(args.smi_at(1) >= 0); uint32_t index = args.smi_at(1); Handle<Object> result; + // TODO(conradw): Investigate strong mode semantics for this. + LanguageMode language_mode = SLOPPY; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, result, - JSObject::GetElementWithInterceptor(receiver, receiver, index, true)); + Object::GetElement(isolate, receiver, index, language_mode)); return *result; } @@ -3054,31 +3074,22 @@ RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { Handle<Name> key = args.at<Name>(1); Handle<Object> result; - if (FLAG_vector_ics) { - DCHECK(args.length() == 4); - Handle<Smi> slot = args.at<Smi>(2); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); - // A monomorphic or polymorphic KeyedLoadIC with a string key can call the - // LoadIC miss handler if the handler misses. Since the vector Nexus is - // set up outside the IC, handle that here. - if (vector->GetKind(vector_slot) == Code::LOAD_IC) { - LoadICNexus nexus(vector, vector_slot); - LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, - ic.Load(receiver, key)); - } else { - DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); - KeyedLoadICNexus nexus(vector, vector_slot); - KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, - ic.Load(receiver, key)); - } + DCHECK(args.length() == 4); + Handle<Smi> slot = args.at<Smi>(2); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + // A monomorphic or polymorphic KeyedLoadIC with a string key can call the + // LoadIC miss handler if the handler misses. Since the vector Nexus is + // set up outside the IC, handle that here. + if (vector->GetKind(vector_slot) == Code::LOAD_IC) { + LoadICNexus nexus(vector, vector_slot); + LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + ic.UpdateState(receiver, key); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); } else { - DCHECK(args.length() == 2); - LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); + KeyedLoadICNexus nexus(vector, vector_slot); + KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); } @@ -3095,5 +3106,5 @@ static const Address IC_utilities[] = { Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/ic.h b/deps/v8/src/ic/ic.h index d51309cffe..dec8318ae5 100644 --- a/deps/v8/src/ic/ic.h +++ b/deps/v8/src/ic/ic.h @@ -7,6 +7,7 @@ #include "src/ic/ic-state.h" #include "src/macro-assembler.h" +#include "src/messages.h" namespace v8 { namespace internal { @@ -77,8 +78,7 @@ class IC { } // Clear the inline cache to initial state. - static void Clear(Isolate* isolate, Address address, - ConstantPoolArray* constant_pool); + static void Clear(Isolate* isolate, Address address, Address constant_pool); #ifdef DEBUG bool IsLoadStub() const { @@ -113,9 +113,10 @@ class IC { } static bool ICUseVector(Code::Kind kind) { - return (FLAG_vector_ics && - (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC)) || - kind == Code::CALL_IC; + return kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || + kind == Code::CALL_IC || + (FLAG_vector_stores && + (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC)); } protected: @@ -134,7 +135,9 @@ class IC { Code* GetOriginalCode() const; bool AddressIsOptimizedCode() const; - bool AddressIsDeoptimizedCode() const; + inline bool AddressIsDeoptimizedCode() const; + inline static bool AddressIsDeoptimizedCode(Isolate* isolate, + Address address); // Set the call-site target. inline void set_target(Code* code); @@ -162,15 +165,15 @@ class IC { void TraceIC(const char* type, Handle<Object> name, State old_state, State new_state); - MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, - Handle<Object> key); + MaybeHandle<Object> TypeError(MessageTemplate::Template, + Handle<Object> object, Handle<Object> key); MaybeHandle<Object> ReferenceError(Handle<Name> name); // Access the target code for the given IC address. static inline Code* GetTargetAtAddress(Address address, - ConstantPoolArray* constant_pool); + Address constant_pool); static inline void SetTargetAtAddress(Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); static void OnTypeFeedbackChanged(Isolate* isolate, Address address, State old_state, State new_state, bool target_remains_ic_stub); @@ -254,8 +257,8 @@ class IC { private: inline Code* raw_target() const; - inline ConstantPoolArray* constant_pool() const; - inline ConstantPoolArray* raw_constant_pool() const; + inline Address constant_pool() const; + inline Address raw_constant_pool() const; void FindTargetMaps() { if (target_maps_set_) return; @@ -275,17 +278,17 @@ class IC { // Frame pointer for the frame that uses (calls) the IC. Address fp_; - // All access to the program counter of an IC structure is indirect - // to make the code GC safe. This feature is crucial since + // All access to the program counter and constant pool of an IC structure is + // indirect to make the code GC safe. This feature is crucial since // GetProperty and SetProperty are called and they in turn might // invoke the garbage collector. Address* pc_address_; - Isolate* isolate_; - // The constant pool of the code which originally called the IC (which might // be for the breakpointed copy of the original code). - Handle<ConstantPoolArray> raw_constant_pool_; + Address* constant_pool_address_; + + Isolate* isolate_; // The original code target that missed. Handle<Code> target_; @@ -351,17 +354,22 @@ class CallIC : public IC { class LoadIC : public IC { public: - static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { - return LoadICState(contextual_mode).GetExtraICState(); + static ExtraICState ComputeExtraICState(ContextualMode contextual_mode, + LanguageMode language_mode) { + return LoadICState(contextual_mode, language_mode).GetExtraICState(); } ContextualMode contextual_mode() const { return LoadICState::GetContextualMode(extra_ic_state()); } + LanguageMode language_mode() const { + return LoadICState::GetLanguageMode(extra_ic_state()); + } + LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) : IC(depth, isolate, nexus) { - DCHECK(!FLAG_vector_ics || nexus != NULL); + DCHECK(nexus != NULL); DCHECK(IsLoadStub()); } @@ -387,19 +395,15 @@ class LoadIC : public IC { // Code generator routines. static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } - static void GeneratePreMonomorphic(MacroAssembler* masm) { - GenerateMiss(masm); - } static void GenerateMiss(MacroAssembler* masm); - static void GenerateNormal(MacroAssembler* masm); - static void GenerateRuntimeGetProperty(MacroAssembler* masm); + static void GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode); + static void GenerateNormal(MacroAssembler* masm, LanguageMode language_mode); static Handle<Code> initialize_stub(Isolate* isolate, ExtraICState extra_state); static Handle<Code> initialize_stub_in_optimized_code( Isolate* isolate, ExtraICState extra_state, State initialization_state); - static Handle<Code> load_global(Isolate* isolate, Handle<GlobalObject> global, - Handle<String> name); MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, Handle<Name> name); @@ -411,10 +415,14 @@ class LoadIC : public IC { Handle<Code> slow_stub() const { if (kind() == Code::LOAD_IC) { - return isolate()->builtins()->LoadIC_Slow(); + return is_strong(language_mode()) + ? isolate()->builtins()->LoadIC_Slow_Strong() + : isolate()->builtins()->LoadIC_Slow(); } else { DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); - return isolate()->builtins()->KeyedLoadIC_Slow(); + return is_strong(language_mode()) + ? isolate()->builtins()->KeyedLoadIC_Slow_Strong() + : isolate()->builtins()->KeyedLoadIC_Slow(); } } @@ -429,14 +437,10 @@ class LoadIC : public IC { CacheHolderFlag cache_holder) override; private: - virtual Handle<Code> pre_monomorphic_stub() const; - static Handle<Code> pre_monomorphic_stub(Isolate* isolate, - ExtraICState extra_state); - Handle<Code> SimpleFieldLoad(FieldIndex index); static void Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); friend class IC; }; @@ -445,11 +449,13 @@ class LoadIC : public IC { class KeyedLoadIC : public LoadIC { public: // ExtraICState bits (building on IC) - class IcCheckTypeField : public BitField<IcCheckType, 1, 1> {}; + class IcCheckTypeField + : public BitField<IcCheckType, LoadICState::kNextBitFieldOffset, 1> {}; static ExtraICState ComputeExtraICState(ContextualMode contextual_mode, + LanguageMode language_mode, IcCheckType key_type) { - return LoadICState(contextual_mode).GetExtraICState() | + return LoadICState(contextual_mode, language_mode).GetExtraICState() | IcCheckTypeField::encode(key_type); } @@ -460,7 +466,7 @@ class KeyedLoadIC : public LoadIC { KeyedLoadIC(FrameDepth depth, Isolate* isolate, KeyedLoadICNexus* nexus = NULL) : LoadIC(depth, isolate, nexus) { - DCHECK(!FLAG_vector_ics || nexus != NULL); + DCHECK(nexus != NULL); DCHECK(target()->is_keyed_load_stub()); } @@ -469,12 +475,11 @@ class KeyedLoadIC : public LoadIC { // Code generator routines. static void GenerateMiss(MacroAssembler* masm); - static void GenerateRuntimeGetProperty(MacroAssembler* masm); + static void GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode); static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } - static void GeneratePreMonomorphic(MacroAssembler* masm) { - GenerateMiss(masm); - } - static void GenerateMegamorphic(MacroAssembler* masm); + static void GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode); // Bit mask to be tested against bit field for the cases when // generic stub should go into slow case. @@ -483,24 +488,22 @@ class KeyedLoadIC : public LoadIC { static const int kSlowCaseBitFieldMask = (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); - static Handle<Code> initialize_stub(Isolate* isolate); + static Handle<Code> initialize_stub(Isolate* isolate, + ExtraICState extra_state); static Handle<Code> initialize_stub_in_optimized_code( - Isolate* isolate, State initialization_state); - static Handle<Code> ChooseMegamorphicStub(Isolate* isolate); - static Handle<Code> pre_monomorphic_stub(Isolate* isolate); + Isolate* isolate, State initialization_state, ExtraICState extra_state); + static Handle<Code> ChooseMegamorphicStub(Isolate* isolate, + ExtraICState extra_state); static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus); protected: // receiver is HeapObject because it could be a String or a JSObject Handle<Code> LoadElementStub(Handle<HeapObject> receiver); - virtual Handle<Code> pre_monomorphic_stub() const { - return pre_monomorphic_stub(isolate()); - } private: static void Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); friend class IC; }; @@ -508,26 +511,17 @@ class KeyedLoadIC : public LoadIC { class StoreIC : public IC { public: - STATIC_ASSERT(i::LANGUAGE_END == 3); - class LanguageModeState : public BitField<LanguageMode, 1, 2> {}; static ExtraICState ComputeExtraICState(LanguageMode flag) { - return LanguageModeState::encode(flag); - } - static LanguageMode GetLanguageMode(ExtraICState state) { - return LanguageModeState::decode(state); + return StoreICState(flag).GetExtraICState(); } - // For convenience, a statically declared encoding of strict mode extra - // IC state. - static const ExtraICState kStrictModeState = STRICT - << LanguageModeState::kShift; - - StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { + StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) + : IC(depth, isolate, nexus) { DCHECK(IsStoreStub()); } LanguageMode language_mode() const { - return LanguageModeState::decode(extra_ic_state()); + return StoreICState::GetLanguageMode(extra_ic_state()); } // Code generators for stub routines. Only called once at startup. @@ -545,6 +539,8 @@ class StoreIC : public IC { static Handle<Code> initialize_stub(Isolate* isolate, LanguageMode language_mode, State initialization_state); + static Handle<Code> initialize_stub_in_optimized_code( + Isolate* isolate, LanguageMode language_mode, State initialization_state); MUST_USE_RESULT MaybeHandle<Object> Store( Handle<Object> object, Handle<Name> name, Handle<Object> value, @@ -554,6 +550,8 @@ class StoreIC : public IC { bool LookupForWrite(LookupIterator* it, Handle<Object> value, JSReceiver::StoreFromKeyed store_mode); + static void Clear(Isolate* isolate, Code* host, StoreICNexus* nexus); + protected: // Stub accessors. Handle<Code> megamorphic_stub() override; @@ -578,7 +576,7 @@ class StoreIC : public IC { inline void set_target(Code* code); static void Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); friend class IC; }; @@ -603,7 +601,7 @@ class KeyedStoreIC : public StoreIC { static ExtraICState ComputeExtraICState(LanguageMode flag, KeyedAccessStoreMode mode) { - return LanguageModeState::encode(flag) | + return StoreICState(flag).GetExtraICState() | ExtraICStateKeyedAccessStoreMode::encode(mode) | IcCheckTypeField::encode(ELEMENT); } @@ -617,7 +615,9 @@ class KeyedStoreIC : public StoreIC { return IcCheckTypeField::decode(extra_state); } - KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) { + KeyedStoreIC(FrameDepth depth, Isolate* isolate, + KeyedStoreICNexus* nexus = NULL) + : StoreIC(depth, isolate, nexus) { DCHECK(target()->is_keyed_store_stub()); } @@ -634,12 +634,16 @@ class KeyedStoreIC : public StoreIC { static void GenerateSlow(MacroAssembler* masm); static void GenerateMegamorphic(MacroAssembler* masm, LanguageMode language_mode); - static void GenerateSloppyArguments(MacroAssembler* masm); static Handle<Code> initialize_stub(Isolate* isolate, LanguageMode language_mode, State initialization_state); + static Handle<Code> initialize_stub_in_optimized_code( + Isolate* isolate, LanguageMode language_mode, State initialization_state); + + static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus); + protected: virtual Handle<Code> pre_monomorphic_stub() const { return pre_monomorphic_stub(isolate(), language_mode()); @@ -659,13 +663,8 @@ class KeyedStoreIC : public StoreIC { private: inline void set_target(Code* code); - // Stub accessors. - Handle<Code> sloppy_arguments_stub() { - return isolate()->builtins()->KeyedStoreIC_SloppyArguments(); - } - static void Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, Handle<Object> key, Handle<Object> value); @@ -683,7 +682,7 @@ class BinaryOpIC : public IC { explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} static Builtins::JavaScript TokenToJSBuiltin(Token::Value op, - LanguageMode language_mode); + Strength strength); MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site, Handle<Object> left, @@ -703,7 +702,8 @@ class CompareIC : public IC { static Condition ComputeCondition(Token::Value op); // Factory method for getting an uninitialized compare stub. - static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op); + static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op, + Strength strength); private: static bool HasInlinedSmiCode(Address address); @@ -711,10 +711,11 @@ class CompareIC : public IC { bool strict() const { return op_ == Token::EQ_STRICT; } Condition GetCondition() const { return ComputeCondition(op_); } - static Code* GetRawUninitialized(Isolate* isolate, Token::Value op); + static Code* GetRawUninitialized(Isolate* isolate, Token::Value op, + Strength strength); static void Clear(Isolate* isolate, Address address, Code* target, - ConstantPoolArray* constant_pool); + Address constant_pool); Token::Value op_; @@ -730,8 +731,7 @@ class CompareNilIC : public IC { static Handle<Code> GetUninitialized(); - static void Clear(Address address, Code* target, - ConstantPoolArray* constant_pool); + static void Clear(Address address, Code* target, Address constant_pool); static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil, Handle<Object> object); diff --git a/deps/v8/src/ic/mips/access-compiler-mips.cc b/deps/v8/src/ic/mips/access-compiler-mips.cc index dce7602ae0..eb519d22e4 100644 --- a/deps/v8/src/ic/mips/access-compiler-mips.cc +++ b/deps/v8/src/ic/mips/access-compiler-mips.cc @@ -40,7 +40,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS diff --git a/deps/v8/src/ic/mips/handler-compiler-mips.cc b/deps/v8/src/ic/mips/handler-compiler-mips.cc index 60df292f41..13ce921b8b 100644 --- a/deps/v8/src/ic/mips/handler-compiler-mips.cc +++ b/deps/v8/src/ic/mips/handler-compiler-mips.cc @@ -778,7 +778,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS diff --git a/deps/v8/src/ic/mips/ic-compiler-mips.cc b/deps/v8/src/ic/mips/ic-compiler-mips.cc index 179531235d..7b88f32331 100644 --- a/deps/v8/src/ic/mips/ic-compiler-mips.cc +++ b/deps/v8/src/ic/mips/ic-compiler-mips.cc @@ -134,7 +134,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS diff --git a/deps/v8/src/ic/mips/ic-mips.cc b/deps/v8/src/ic/mips/ic-mips.cc index 33b78cec58..5a6f95a231 100644 --- a/deps/v8/src/ic/mips/ic-mips.cc +++ b/deps/v8/src/ic/mips/ic-mips.cc @@ -163,7 +163,8 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch1, Register scratch2, - Register result, Label* slow) { + Register result, Label* slow, + LanguageMode language_mode) { // Register use: // // receiver - holds the receiver on entry. @@ -185,7 +186,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // // scratch2 - used to hold maps, prototypes, and the loaded value. Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(elements); @@ -203,7 +204,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ lw(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ LoadRoot(at, Heap::kNullValueRootIndex); - __ Branch(&return_undefined, eq, scratch2, Operand(at)); + __ Branch(&absent, eq, scratch2, Operand(at)); __ lw(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); __ lw(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -218,9 +219,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ Branch(slow, ne, elements, Operand(at)); __ Branch(&check_next_prototype); - __ bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ Branch(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ Branch(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ Branch(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -270,7 +276,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = a0; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -285,7 +291,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } @@ -296,14 +302,10 @@ static const Register LoadIC_TempRegister() { return a3; } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); - __ Push(receiver, name, slot, vector); - } else { - __ Push(receiver, name); - } + __ Push(receiver, name, slot, vector); } @@ -311,138 +313,30 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in ra. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(t0, t1, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->load_miss(), 1, t0, t1); LoadIC_PushArgs(masm); // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); -} - - -static MemOperand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Register scratch3, Label* unmapped_case, - Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the map check - // later, we do not need to check for interceptors or whether it - // requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ GetObjectType(object, scratch1, scratch2); - __ Branch(slow_case, lt, scratch2, Operand(FIRST_JS_RECEIVER_TYPE)); - - // Check that the key is a positive smi. - __ And(scratch1, key, Operand(0x80000001)); - __ Branch(slow_case, ne, scratch1, Operand(zero_reg)); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ lw(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ lw(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); - __ Subu(scratch2, scratch2, Operand(Smi::FromInt(2))); - __ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2)); - - // Load element index and check whether it is the hole. - const int kOffset = - FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; - - __ li(scratch3, Operand(kPointerSize >> 1)); - __ Mul(scratch3, key, scratch3); - __ Addu(scratch3, scratch3, Operand(kOffset)); - - __ Addu(scratch2, scratch1, scratch3); - __ lw(scratch2, MemOperand(scratch2)); - __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - __ Branch(unmapped_case, eq, scratch2, Operand(scratch3)); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - __ lw(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); - __ li(scratch3, Operand(kPointerSize >> 1)); - __ Mul(scratch3, scratch2, scratch3); - __ Addu(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag)); - __ Addu(scratch2, scratch1, scratch3); - return MemOperand(scratch2); -} - - -static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. The parameter_map register - // must be loaded with the parameter map of the arguments object and is - // overwritten. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ lw(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); - __ CheckMap(backing_store, scratch, Heap::kFixedArrayMapRootIndex, slow_case, - DONT_DO_SMI_CHECK); - __ lw(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); - __ Branch(slow_case, Ugreater_equal, key, Operand(scratch)); - __ li(scratch, Operand(kPointerSize >> 1)); - __ Mul(scratch, key, scratch); - __ Addu(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - __ Addu(scratch, backing_store, scratch); - return MemOperand(scratch); -} - - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(value.is(a0)); - - Label slow, notin; - // Store address is returned in register (of MemOperand) mapped_location. - MemOperand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, key, a3, t0, t1, ¬in, &slow); - __ sw(value, mapped_location); - __ mov(t5, value); - DCHECK_EQ(mapped_location.offset(), 0); - __ RecordWrite(a3, mapped_location.rm(), t5, kRAHasNotBeenSaved, - kDontSaveFPRegs); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, value); // (In delay slot) return the value stored in v0. - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in a3. - // Store address is returned in register (of MemOperand) unmapped_location. - MemOperand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, key, a3, t0, &slow); - __ sw(value, unmapped_location); - __ mov(t5, value); - DCHECK_EQ(unmapped_location.offset(), 0); - __ RecordWrite(a3, unmapped_location.rm(), t5, kRAHasNotBeenSaved, - kDontSaveFPRegs); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); // (In delay slot) return the value stored in v0. - __ bind(&slow); - GenerateMiss(masm); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -450,9 +344,8 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in ra. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(t0, t1, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, t0, t1); LoadIC_PushArgs(masm); @@ -461,21 +354,26 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -499,7 +397,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(a0, a3, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, a0, a3, t0, v0, &slow); + GenerateFastArrayLoad(masm, receiver, key, a0, a3, t0, v0, &slow, + language_mode); __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, t0, a3); __ Ret(); @@ -520,7 +419,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, t0, a3); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); @@ -536,19 +435,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ LoadRoot(at, Heap::kHashTableMapRootIndex); __ Branch(&probe_dictionary, eq, t0, Operand(at)); - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(vector, slot, t0, t1, t2, t5)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); - __ li(slot, Operand(Smi::FromInt(int_slot))); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, t0, t1, t2, t5)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); + __ li(slot, Operand(Smi::FromInt(slot_index))); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -782,6 +678,20 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ lw(t0, FieldMemOperand(key, HeapObject::kMapOffset)); __ lb(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(t0, &slow); + + if (FLAG_vector_stores) { + // 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. + Register vector = VectorStoreICDescriptor::VectorRegister(); + Register slot = VectorStoreICDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, a3, t0, t1, t2)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedStoreDummyVectorRootIndex); + __ li(slot, Operand(Smi::FromInt(slot_index))); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -990,7 +900,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.ChangeBranchCondition(eq); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS diff --git a/deps/v8/src/ic/mips/stub-cache-mips.cc b/deps/v8/src/ic/mips/stub-cache-mips.cc index fab66d8963..2048531aba 100644 --- a/deps/v8/src/ic/mips/stub-cache-mips.cc +++ b/deps/v8/src/ic/mips/stub-cache-mips.cc @@ -121,8 +121,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // extra3 don't conflict with the vector and slot registers, which need // to be preserved for a handler call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); } #endif @@ -169,7 +169,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS diff --git a/deps/v8/src/ic/mips64/access-compiler-mips64.cc b/deps/v8/src/ic/mips64/access-compiler-mips64.cc index 5e3cfc52fd..74b4b93240 100644 --- a/deps/v8/src/ic/mips64/access-compiler-mips64.cc +++ b/deps/v8/src/ic/mips64/access-compiler-mips64.cc @@ -40,7 +40,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS64 diff --git a/deps/v8/src/ic/mips64/handler-compiler-mips64.cc b/deps/v8/src/ic/mips64/handler-compiler-mips64.cc index f60e8c6a43..d83c807e3c 100644 --- a/deps/v8/src/ic/mips64/handler-compiler-mips64.cc +++ b/deps/v8/src/ic/mips64/handler-compiler-mips64.cc @@ -779,7 +779,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS64 diff --git a/deps/v8/src/ic/mips64/ic-compiler-mips64.cc b/deps/v8/src/ic/mips64/ic-compiler-mips64.cc index a3dcdf7207..df67fb9a81 100644 --- a/deps/v8/src/ic/mips64/ic-compiler-mips64.cc +++ b/deps/v8/src/ic/mips64/ic-compiler-mips64.cc @@ -134,7 +134,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS64 diff --git a/deps/v8/src/ic/mips64/ic-mips64.cc b/deps/v8/src/ic/mips64/ic-mips64.cc index 1ec49c45d4..a6075dfcaa 100644 --- a/deps/v8/src/ic/mips64/ic-mips64.cc +++ b/deps/v8/src/ic/mips64/ic-mips64.cc @@ -162,7 +162,8 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch1, Register scratch2, - Register result, Label* slow) { + Register result, Label* slow, + LanguageMode language_mode) { // Register use: // // receiver - holds the receiver on entry. @@ -184,7 +185,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // // scratch2 - used to hold maps, prototypes, and the loaded value. Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(elements); @@ -202,7 +203,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ ld(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ LoadRoot(at, Heap::kNullValueRootIndex); - __ Branch(&return_undefined, eq, scratch2, Operand(at)); + __ Branch(&absent, eq, scratch2, Operand(at)); __ ld(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); __ ld(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -217,9 +218,13 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ Branch(slow, ne, elements, Operand(at)); __ Branch(&check_next_prototype); - __ bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ Branch(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + __ Branch(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ Branch(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -269,7 +274,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = a0; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -283,7 +288,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } @@ -294,14 +299,10 @@ static const Register LoadIC_TempRegister() { return a3; } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); - __ Push(receiver, name, slot, vector); - } else { - __ Push(receiver, name); - } + __ Push(receiver, name, slot, vector); } @@ -309,138 +310,30 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is on the stack. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(a4, a5, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->load_miss(), 1, a4, a5); LoadIC_PushArgs(masm); // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); -} - - -static MemOperand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Register scratch3, Label* unmapped_case, - Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the map check - // later, we do not need to check for interceptors or whether it - // requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ GetObjectType(object, scratch1, scratch2); - __ Branch(slow_case, lt, scratch2, Operand(FIRST_JS_RECEIVER_TYPE)); - - // Check that the key is a positive smi. - __ NonNegativeSmiTst(key, scratch1); - __ Branch(slow_case, ne, scratch1, Operand(zero_reg)); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ ld(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ ld(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); - __ Dsubu(scratch2, scratch2, Operand(Smi::FromInt(2))); - __ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2)); - - // Load element index and check whether it is the hole. - const int kOffset = - FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; - - __ SmiUntag(scratch3, key); - __ dsll(scratch3, scratch3, kPointerSizeLog2); - __ Daddu(scratch3, scratch3, Operand(kOffset)); - - __ Daddu(scratch2, scratch1, scratch3); - __ ld(scratch2, MemOperand(scratch2)); - __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - __ Branch(unmapped_case, eq, scratch2, Operand(scratch3)); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - __ ld(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); - __ SmiUntag(scratch3, scratch2); - __ dsll(scratch3, scratch3, kPointerSizeLog2); - __ Daddu(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag)); - __ Daddu(scratch2, scratch1, scratch3); - return MemOperand(scratch2); -} - - -static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. The parameter_map register - // must be loaded with the parameter map of the arguments object and is - // overwritten. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ ld(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); - __ CheckMap(backing_store, scratch, Heap::kFixedArrayMapRootIndex, slow_case, - DONT_DO_SMI_CHECK); - __ ld(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); - __ Branch(slow_case, Ugreater_equal, key, Operand(scratch)); - __ SmiUntag(scratch, key); - __ dsll(scratch, scratch, kPointerSizeLog2); - __ Daddu(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - __ Daddu(scratch, backing_store, scratch); - return MemOperand(scratch); -} - - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(value.is(a0)); - - Label slow, notin; - // Store address is returned in register (of MemOperand) mapped_location. - MemOperand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, key, a3, a4, a5, ¬in, &slow); - __ sd(value, mapped_location); - __ mov(t1, value); - DCHECK_EQ(mapped_location.offset(), 0); - __ RecordWrite(a3, mapped_location.rm(), t1, kRAHasNotBeenSaved, - kDontSaveFPRegs); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, value); // (In delay slot) return the value stored in v0. - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in a3. - // Store address is returned in register (of MemOperand) unmapped_location. - MemOperand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, key, a3, a4, &slow); - __ sd(value, unmapped_location); - __ mov(t1, value); - DCHECK_EQ(unmapped_location.offset(), 0); - __ RecordWrite(a3, unmapped_location.rm(), t1, kRAHasNotBeenSaved, - kDontSaveFPRegs); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); // (In delay slot) return the value stored in v0. - __ bind(&slow); - GenerateMiss(masm); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -448,9 +341,8 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in ra. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(a4, a5, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a4, a5); LoadIC_PushArgs(masm); @@ -459,21 +351,26 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in ra. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -497,7 +394,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(a0, a3, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, &slow); + GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, &slow, + language_mode); __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3); __ Ret(); @@ -518,7 +416,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, a4, a3); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); @@ -534,19 +432,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ LoadRoot(at, Heap::kHashTableMapRootIndex); __ Branch(&probe_dictionary, eq, a4, Operand(at)); - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(vector, slot, a4, a5, a6, t1)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); - __ li(slot, Operand(Smi::FromInt(int_slot))); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, a4, a5, a6, t1)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); + __ li(slot, Operand(Smi::FromInt(slot_index))); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -784,6 +679,20 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ ld(a4, FieldMemOperand(key, HeapObject::kMapOffset)); __ lb(a4, FieldMemOperand(a4, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(a4, &slow); + + if (FLAG_vector_stores) { + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, a3, a4, a5, a6)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedStoreDummyVectorRootIndex); + __ li(slot, Operand(Smi::FromInt(slot_index))); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -990,7 +899,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.ChangeBranchCondition(eq); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS64 diff --git a/deps/v8/src/ic/mips64/stub-cache-mips64.cc b/deps/v8/src/ic/mips64/stub-cache-mips64.cc index 04883d7bc9..0d612903aa 100644 --- a/deps/v8/src/ic/mips64/stub-cache-mips64.cc +++ b/deps/v8/src/ic/mips64/stub-cache-mips64.cc @@ -57,14 +57,16 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, __ Branch(&miss, ne, name, Operand(at)); // Check the map matches. - __ ld(at, MemOperand(base_addr, map_off_addr - key_off_addr)); + __ ld(at, MemOperand(base_addr, + static_cast<int32_t>(map_off_addr - key_off_addr))); __ ld(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); __ Branch(&miss, ne, at, Operand(scratch2)); // Get the code entry from the cache. Register code = scratch2; scratch2 = no_reg; - __ ld(code, MemOperand(base_addr, value_off_addr - key_off_addr)); + __ ld(code, MemOperand(base_addr, + static_cast<int32_t>(value_off_addr - key_off_addr))); // Check that the flags match what we're looking for. Register flags_reg = base_addr; @@ -122,8 +124,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // extra3 don't conflict with the vector and slot registers, which need // to be preserved for a handler call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); } #endif @@ -170,7 +172,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_MIPS64 diff --git a/deps/v8/src/ic/ppc/access-compiler-ppc.cc b/deps/v8/src/ic/ppc/access-compiler-ppc.cc index e98f5172f8..aa3859a62c 100644 --- a/deps/v8/src/ic/ppc/access-compiler-ppc.cc +++ b/deps/v8/src/ic/ppc/access-compiler-ppc.cc @@ -40,7 +40,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_PPC diff --git a/deps/v8/src/ic/ppc/handler-compiler-ppc.cc b/deps/v8/src/ic/ppc/handler-compiler-ppc.cc index 5cb6f226bf..8988b08e2c 100644 --- a/deps/v8/src/ic/ppc/handler-compiler-ppc.cc +++ b/deps/v8/src/ic/ppc/handler-compiler-ppc.cc @@ -25,7 +25,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( // -- lr : return address // ----------------------------------- { - FrameScope scope(masm, StackFrame::INTERNAL); + FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); if (accessor_index >= 0) { DCHECK(!holder.is(scratch)); @@ -62,7 +62,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( // -- lr : return address // ----------------------------------- { - FrameScope scope(masm, StackFrame::INTERNAL); + FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); // Save value register, so we can restore it later. __ push(value()); @@ -649,7 +649,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( // Save necessary data before invoking an interceptor. // Requires a frame to make GC aware of pushed pointers. { - FrameScope frame_scope(masm(), StackFrame::INTERNAL); + FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); if (must_preserve_receiver_reg) { __ Push(receiver(), holder_reg, this->name()); } else { @@ -784,7 +784,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/ic/ppc/ic-compiler-ppc.cc b/deps/v8/src/ic/ppc/ic-compiler-ppc.cc index 9f33a59e7b..ad72c231de 100644 --- a/deps/v8/src/ic/ppc/ic-compiler-ppc.cc +++ b/deps/v8/src/ic/ppc/ic-compiler-ppc.cc @@ -129,7 +129,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_PPC diff --git a/deps/v8/src/ic/ppc/ic-ppc.cc b/deps/v8/src/ic/ppc/ic-ppc.cc index d0a2177f20..db56fbaf66 100644 --- a/deps/v8/src/ic/ppc/ic-ppc.cc +++ b/deps/v8/src/ic/ppc/ic-ppc.cc @@ -167,7 +167,8 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch1, Register scratch2, - Register result, Label* slow) { + Register result, Label* slow, + LanguageMode language_mode) { // Register use: // // receiver - holds the receiver on entry. @@ -189,7 +190,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // // scratch2 - used to hold maps, prototypes, and the loaded value. Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(elements); @@ -208,7 +209,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ LoadP(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ CompareRoot(scratch2, Heap::kNullValueRootIndex); - __ beq(&return_undefined); + __ beq(&absent); __ LoadP(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); __ LoadP(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -223,9 +224,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ bne(slow); __ jmp(&check_next_prototype); - __ bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ jmp(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ jmp(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ jmp(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -273,7 +279,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = r3; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -288,7 +294,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } @@ -299,14 +305,10 @@ static const Register LoadIC_TempRegister() { return r6; } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); - __ Push(receiver, name, slot, vector); - } else { - __ Push(receiver, name); - } + __ Push(receiver, name, slot, vector); } @@ -314,138 +316,30 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in lr. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(r7, r8, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->load_miss(), 1, r7, r8); LoadIC_PushArgs(masm); // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ mr(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); -} - - -static MemOperand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Register scratch3, Label* unmapped_case, - Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the map check - // later, we do not need to check for interceptors or whether it - // requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_RECEIVER_TYPE); - __ blt(slow_case); - - // Check that the key is a positive smi. - __ mov(scratch1, Operand(0x80000001)); - __ and_(r0, key, scratch1, SetRC); - __ bne(slow_case, cr0); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ LoadP(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ LoadP(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); - __ SubSmiLiteral(scratch2, scratch2, Smi::FromInt(2), r0); - __ cmpl(key, scratch2); - __ bge(unmapped_case); - - // Load element index and check whether it is the hole. - const int kOffset = - FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; - - __ SmiToPtrArrayOffset(scratch3, key); - __ addi(scratch3, scratch3, Operand(kOffset)); - - __ LoadPX(scratch2, MemOperand(scratch1, scratch3)); - __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - __ cmp(scratch2, scratch3); - __ beq(unmapped_case); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - __ LoadP(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); - __ SmiToPtrArrayOffset(scratch3, scratch2); - __ addi(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag)); - return MemOperand(scratch1, scratch3); -} - - -static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. The parameter_map register - // must be loaded with the parameter map of the arguments object and is - // overwritten. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ LoadP(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, scratch, fixed_array_map, slow_case, - DONT_DO_SMI_CHECK); - __ LoadP(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); - __ cmpl(key, scratch); - __ bge(slow_case); - __ SmiToPtrArrayOffset(scratch, key); - __ addi(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - return MemOperand(backing_store, scratch); -} - - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(receiver.is(r4)); - DCHECK(key.is(r5)); - DCHECK(value.is(r3)); - - Label slow, notin; - MemOperand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, key, r6, r7, r8, ¬in, &slow); - Register mapped_base = mapped_location.ra(); - Register mapped_offset = mapped_location.rb(); - __ StorePX(value, mapped_location); - __ add(r9, mapped_base, mapped_offset); - __ mr(r11, value); - __ RecordWrite(mapped_base, r9, r11, kLRHasNotBeenSaved, kDontSaveFPRegs); - __ Ret(); - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in r6. - MemOperand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, key, r6, r7, &slow); - Register unmapped_base = unmapped_location.ra(); - Register unmapped_offset = unmapped_location.rb(); - __ StorePX(value, unmapped_location); - __ add(r9, unmapped_base, unmapped_offset); - __ mr(r11, value); - __ RecordWrite(unmapped_base, r9, r11, kLRHasNotBeenSaved, kDontSaveFPRegs); - __ Ret(); - __ bind(&slow); - GenerateMiss(masm); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -453,9 +347,8 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // The return address is in lr. Isolate* isolate = masm->isolate(); - DCHECK(!FLAG_vector_ics || - !AreAliased(r7, r8, VectorLoadICDescriptor::SlotRegister(), - VectorLoadICDescriptor::VectorRegister())); + DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(), + LoadWithVectorDescriptor::VectorRegister())); __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r7, r8); LoadIC_PushArgs(masm); @@ -463,21 +356,26 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is in lr. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -501,7 +399,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(r3, r6, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, r3, r6, r7, r3, &slow); + GenerateFastArrayLoad(masm, receiver, key, r3, r6, r7, r3, &slow, + language_mode); __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r7, r6); __ Ret(); @@ -523,7 +422,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r7, r6); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, r3, r6, &index_name, &slow); @@ -540,19 +439,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ beq(&probe_dictionary); - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(vector, slot, r7, r8, r9, r10)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); - __ LoadSmiLiteral(slot, Smi::FromInt(int_slot)); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, r7, r8, r9, r10)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex); + __ LoadSmiLiteral(slot, Smi::FromInt(slot_index)); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -803,6 +699,20 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ LoadP(r7, FieldMemOperand(key, HeapObject::kMapOffset)); __ lbz(r7, FieldMemOperand(r7, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(r7, &slow); + + if (FLAG_vector_stores) { + // 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. + Register vector = VectorStoreICDescriptor::VectorRegister(); + Register slot = VectorStoreICDescriptor::SlotRegister(); + DCHECK(!AreAliased(vector, slot, r6, r7, r8, r9)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ LoadRoot(vector, Heap::kKeyedStoreDummyVectorRootIndex); + __ LoadSmiLiteral(slot, Smi::FromInt(slot_index)); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -994,11 +904,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.masm()->TestIfSmi(reg, r0); } else { DCHECK(check == DISABLE_INLINED_SMI_CHECK); -#if V8_TARGET_ARCH_PPC64 - DCHECK(Assembler::IsRldicl(instr_at_patch)); -#else - DCHECK(Assembler::IsRlwinm(instr_at_patch)); -#endif + DCHECK(Assembler::IsAndi(instr_at_patch)); patcher.masm()->cmp(reg, reg, cr0); } DCHECK(Assembler::IsBranch(branch_instr)); @@ -1011,7 +917,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { patcher.EmitCondition(eq); } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_PPC diff --git a/deps/v8/src/ic/ppc/stub-cache-ppc.cc b/deps/v8/src/ic/ppc/stub-cache-ppc.cc index 50f1f99850..57b32452d6 100644 --- a/deps/v8/src/ic/ppc/stub-cache-ppc.cc +++ b/deps/v8/src/ic/ppc/stub-cache-ppc.cc @@ -142,8 +142,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // extra3 don't conflict with the vector and slot registers, which need // to be preserved for a handler call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadWithVectorDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); } #endif @@ -187,7 +187,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_PPC diff --git a/deps/v8/src/ic/stub-cache.cc b/deps/v8/src/ic/stub-cache.cc index e3a4938d6a..630e671613 100644 --- a/deps/v8/src/ic/stub-cache.cc +++ b/deps/v8/src/ic/stub-cache.cc @@ -143,5 +143,5 @@ void StubCache::CollectMatchingMaps(SmallMapList* types, Handle<Name> name, } } } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ic/x64/access-compiler-x64.cc b/deps/v8/src/ic/x64/access-compiler-x64.cc index cd9196f526..6acc950bc0 100644 --- a/deps/v8/src/ic/x64/access-compiler-x64.cc +++ b/deps/v8/src/ic/x64/access-compiler-x64.cc @@ -40,7 +40,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/ic/x64/handler-compiler-x64.cc b/deps/v8/src/ic/x64/handler-compiler-x64.cc index 8288d8943d..43754c32b1 100644 --- a/deps/v8/src/ic/x64/handler-compiler-x64.cc +++ b/deps/v8/src/ic/x64/handler-compiler-x64.cc @@ -803,7 +803,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/ic/x64/ic-compiler-x64.cc b/deps/v8/src/ic/x64/ic-compiler-x64.cc index 89e7aee7ff..4fcd7b7d3c 100644 --- a/deps/v8/src/ic/x64/ic-compiler-x64.cc +++ b/deps/v8/src/ic/x64/ic-compiler-x64.cc @@ -136,7 +136,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/ic/x64/ic-x64.cc b/deps/v8/src/ic/x64/ic-x64.cc index c183febbb8..3556d21000 100644 --- a/deps/v8/src/ic/x64/ic-x64.cc +++ b/deps/v8/src/ic/x64/ic-x64.cc @@ -171,7 +171,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register elements, Register scratch, Register result, - Label* slow) { + Label* slow, LanguageMode language_mode) { // Register use: // // receiver - holds the receiver on entry. @@ -191,7 +191,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // // scratch - used to hold maps, prototypes, and the loaded value. Label check_prototypes, check_next_prototype; - Label done, in_bounds, return_undefined; + Label done, in_bounds, absent; __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(elements); @@ -210,7 +210,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); // scratch: current prototype __ CompareRoot(scratch, Heap::kNullValueRootIndex); - __ j(equal, &return_undefined); + __ j(equal, &absent); __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset)); __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); // elements: elements of current prototype @@ -225,9 +225,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ j(not_equal, slow); __ jmp(&check_next_prototype); - __ bind(&return_undefined); - __ LoadRoot(result, Heap::kUndefinedValueRootIndex); - __ jmp(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ jmp(slow); + } else { + __ LoadRoot(result, Heap::kUndefinedValueRootIndex); + __ jmp(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -274,7 +279,8 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is on the stack. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -296,7 +302,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // Check the receiver's map to see if it has fast elements. __ CheckFastElements(rax, &check_number_dictionary); - GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow); + GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow, + language_mode); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->keyed_load_generic_smi(), 1); __ ret(0); @@ -317,7 +324,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); // Slow case: Jump to runtime. __ IncrementCounter(counters->keyed_load_generic_slow(), 1); - GenerateRuntimeGetProperty(masm); + KeyedLoadIC::GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); @@ -333,19 +340,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ j(equal, &probe_dictionary); Register megamorphic_scratch = rdi; - 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. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); - DCHECK(!AreAliased(megamorphic_scratch, vector, slot)); - Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( - masm->isolate()->factory()->keyed_load_dummy_vector()); - int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); - __ Move(vector, dummy_vector); - __ Move(slot, Smi::FromInt(int_slot)); - } + // 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. + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); + DCHECK(!AreAliased(megamorphic_scratch, vector, slot)); + Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast( + masm->isolate()->factory()->keyed_load_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ Move(vector, dummy_vector); + __ Move(slot, Smi::FromInt(slot_index)); Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::LOAD_IC)); @@ -559,6 +563,19 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ movp(r9, FieldOperand(key, HeapObject::kMapOffset)); __ movzxbp(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(r9, &slow_with_tagged_index); + + if (FLAG_vector_stores) { + Register vector = VectorStoreICDescriptor::VectorRegister(); + Register slot = VectorStoreICDescriptor::SlotRegister(); + // 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( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot_index = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ Move(vector, dummy_vector); + __ Move(slot, Smi::FromInt(slot_index)); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( @@ -611,111 +628,7 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, } -static Operand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Register scratch3, Label* unmapped_case, - Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - - // Check that the receiver is a JSObject. Because of the elements - // map check later, we do not need to check for interceptors or - // whether it requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); - __ j(below, slow_case); - - // Check that the key is a positive smi. - Condition check = masm->CheckNonNegativeSmi(key); - __ j(NegateCondition(check), slow_case); - - // Load the elements into scratch1 and check its map. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ movp(scratch1, FieldOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. - __ movp(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); - __ SmiSubConstant(scratch2, scratch2, Smi::FromInt(2)); - __ cmpp(key, scratch2); - __ j(greater_equal, unmapped_case); - - // Load element index and check whether it is the hole. - const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; - __ SmiToInteger64(scratch3, key); - __ movp(scratch2, - FieldOperand(scratch1, scratch3, times_pointer_size, kHeaderSize)); - __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex); - __ j(equal, unmapped_case); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - __ movp(scratch1, FieldOperand(scratch1, FixedArray::kHeaderSize)); - __ SmiToInteger64(scratch3, scratch2); - return FieldOperand(scratch1, scratch3, times_pointer_size, - Context::kHeaderSize); -} - - -static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. The parameter_map register - // must be loaded with the parameter map of the arguments object and is - // overwritten. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ movp(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); - __ movp(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); - __ cmpp(key, scratch); - __ j(greater_equal, slow_case); - __ SmiToInteger64(scratch, key); - return FieldOperand(backing_store, scratch, times_pointer_size, - FixedArray::kHeaderSize); -} - - -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - // The return address is on the stack. - Label slow, notin; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(receiver.is(rdx)); - DCHECK(name.is(rcx)); - DCHECK(value.is(rax)); - - Operand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, name, rbx, rdi, r8, ¬in, &slow); - __ movp(mapped_location, value); - __ leap(r9, mapped_location); - __ movp(r8, value); - __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, - INLINE_SMI_CHECK); - __ Ret(); - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in rbx. - Operand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow); - __ movp(unmapped_location, value); - __ leap(r9, unmapped_location); - __ movp(r8, value); - __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, - INLINE_SMI_CHECK); - __ Ret(); - __ bind(&slow); - GenerateMiss(masm); -} - - -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = rax; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -730,33 +643,24 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + LoadIC::GenerateRuntimeGetProperty(masm, language_mode); } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); - DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) && - !rdi.is(vector)); - - __ PopReturnAddressTo(rdi); - __ Push(receiver); - __ Push(name); - __ Push(slot); - __ Push(vector); - __ PushReturnAddressFrom(rdi); - } else { - DCHECK(!rbx.is(receiver) && !rbx.is(name)); + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) && + !rdi.is(vector)); - __ PopReturnAddressTo(rbx); - __ Push(receiver); - __ Push(name); - __ PushReturnAddressFrom(rbx); - } + __ PopReturnAddressTo(rdi); + __ Push(receiver); + __ Push(name); + __ Push(slot); + __ Push(vector); + __ PushReturnAddressFrom(rdi); } @@ -771,15 +675,17 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); + DCHECK(!rbx.is(receiver) && !rbx.is(name)); __ PopReturnAddressTo(rbx); @@ -787,8 +693,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ Push(name); __ PushReturnAddressFrom(rbx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -802,15 +710,17 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); + DCHECK(!rbx.is(receiver) && !rbx.is(name)); __ PopReturnAddressTo(rbx); @@ -818,8 +728,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ Push(name); __ PushReturnAddressFrom(rbx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } @@ -965,7 +877,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/ic/x64/stub-cache-x64.cc b/deps/v8/src/ic/x64/stub-cache-x64.cc index 4be0d5b330..34f51626a6 100644 --- a/deps/v8/src/ic/x64/stub-cache-x64.cc +++ b/deps/v8/src/ic/x64/stub-cache-x64.cc @@ -115,8 +115,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, // the vector and slot registers, which need to be preserved for a handler // call or miss. if (IC::ICUseVector(ic_kind)) { - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); DCHECK(!AreAliased(vector, slot, scratch)); } #endif @@ -161,7 +161,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/ic/x87/access-compiler-x87.cc b/deps/v8/src/ic/x87/access-compiler-x87.cc index 9456ec899c..d5fde5d4b8 100644 --- a/deps/v8/src/ic/x87/access-compiler-x87.cc +++ b/deps/v8/src/ic/x87/access-compiler-x87.cc @@ -38,7 +38,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { } #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X87 diff --git a/deps/v8/src/ic/x87/handler-compiler-x87.cc b/deps/v8/src/ic/x87/handler-compiler-x87.cc index e9c8e4f713..056bd952c7 100644 --- a/deps/v8/src/ic/x87/handler-compiler-x87.cc +++ b/deps/v8/src/ic/x87/handler-compiler-x87.cc @@ -130,10 +130,9 @@ void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( MacroAssembler* masm, Register receiver, Register scratch1, Register scratch2, Label* miss_label) { - DCHECK(!FLAG_vector_ics); - __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); - __ mov(eax, scratch1); - __ ret(0); + // TODO(mvstanton): This isn't used on ia32. Move all the other + // platform implementations into a code stub so this method can be removed. + UNREACHABLE(); } @@ -809,7 +808,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X87 diff --git a/deps/v8/src/ic/x87/ic-compiler-x87.cc b/deps/v8/src/ic/x87/ic-compiler-x87.cc index 160e9e9c67..3697708037 100644 --- a/deps/v8/src/ic/x87/ic-compiler-x87.cc +++ b/deps/v8/src/ic/x87/ic-compiler-x87.cc @@ -128,7 +128,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X87 diff --git a/deps/v8/src/ic/x87/ic-x87.cc b/deps/v8/src/ic/x87/ic-x87.cc index 92005bd097..b863c69132 100644 --- a/deps/v8/src/ic/x87/ic-x87.cc +++ b/deps/v8/src/ic/x87/ic-x87.cc @@ -172,7 +172,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, Register key, Register scratch, Register scratch2, Register result, - Label* slow) { + Label* slow, LanguageMode language_mode) { // Register use: // receiver - holds the receiver and is unchanged. // key - holds the key and is unchanged (must be a smi). @@ -182,7 +182,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, // 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; + Label done, in_bounds, absent; __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); __ AssertFastElements(scratch); @@ -200,7 +200,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset)); // scratch2: current prototype __ cmp(scratch2, masm->isolate()->factory()->null_value()); - __ j(equal, &return_undefined); + __ j(equal, &absent); __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset)); __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset)); // scratch: elements of current prototype @@ -215,9 +215,14 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, __ j(not_equal, slow); __ jmp(&check_next_prototype); - __ bind(&return_undefined); - __ mov(result, masm->isolate()->factory()->undefined_value()); - __ jmp(&done); + __ bind(&absent); + if (is_strong(language_mode)) { + // Strong mode accesses must throw in this case, so call the runtime. + __ jmp(slow); + } else { + __ mov(result, masm->isolate()->factory()->undefined_value()); + __ jmp(&done); + } __ bind(&in_bounds); // Fast case: Do the load. @@ -263,74 +268,8 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, } -static Operand GenerateMappedArgumentsLookup( - MacroAssembler* masm, Register object, Register key, Register scratch1, - Register scratch2, Label* unmapped_case, Label* slow_case) { - Heap* heap = masm->isolate()->heap(); - Factory* factory = masm->isolate()->factory(); - - // Check that the receiver is a JSObject. Because of the elements - // map check later, we do not need to check for interceptors or - // whether it requires access checks. - __ JumpIfSmi(object, slow_case); - // Check that the object is some kind of JSObject. - __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); - __ j(below, slow_case); - - // Check that the key is a positive smi. - __ test(key, Immediate(0x80000001)); - __ j(not_zero, slow_case); - - // Load the elements into scratch1 and check its map. - Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); - __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset)); - __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); - - // Check if element is in the range of mapped arguments. If not, jump - // to the unmapped lookup with the parameter map in scratch1. - __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); - __ sub(scratch2, Immediate(Smi::FromInt(2))); - __ cmp(key, scratch2); - __ j(above_equal, unmapped_case); - - // Load element index and check whether it is the hole. - const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; - __ mov(scratch2, - FieldOperand(scratch1, key, times_half_pointer_size, kHeaderSize)); - __ cmp(scratch2, factory->the_hole_value()); - __ j(equal, unmapped_case); - - // Load value from context and return it. We can reuse scratch1 because - // we do not jump to the unmapped lookup (which requires the parameter - // map in scratch1). - const int kContextOffset = FixedArray::kHeaderSize; - __ mov(scratch1, FieldOperand(scratch1, kContextOffset)); - return FieldOperand(scratch1, scratch2, times_half_pointer_size, - Context::kHeaderSize); -} - - -static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, - Register key, - Register parameter_map, - Register scratch, - Label* slow_case) { - // Element is in arguments backing store, which is referenced by the - // second element of the parameter_map. - const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; - Register backing_store = parameter_map; - __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); - Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); - __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); - __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); - __ cmp(key, scratch); - __ j(greater_equal, slow_case); - return FieldOperand(backing_store, key, times_half_pointer_size, - FixedArray::kHeaderSize); -} - - -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { +void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, + LanguageMode language_mode) { // The return address is on the stack. Label slow, check_name, index_smi, index_name, property_array_property; Label probe_dictionary, check_number_dictionary; @@ -352,7 +291,8 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { // 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); + GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow, + language_mode); Isolate* isolate = masm->isolate(); Counters* counters = isolate->counters(); __ IncrementCounter(counters->keyed_load_generic_smi(), 1); @@ -384,7 +324,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { __ bind(&slow); // Slow case: jump to runtime. __ IncrementCounter(counters->keyed_load_generic_slow(), 1); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); __ bind(&check_name); GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); @@ -399,26 +339,21 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { Immediate(isolate->factory()->hash_table_map())); __ j(equal, &probe_dictionary); - 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)); - } + // 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)); 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); - if (FLAG_vector_ics) { - __ pop(VectorLoadICDescriptor::VectorRegister()); - __ pop(VectorLoadICDescriptor::SlotRegister()); - } + __ pop(LoadWithVectorDescriptor::VectorRegister()); + __ pop(LoadDescriptor::SlotRegister()); // Cache miss. GenerateMiss(masm); @@ -442,37 +377,6 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { } -void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { - // Return address is on the stack. - Label slow, notin; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - DCHECK(receiver.is(edx)); - DCHECK(name.is(ecx)); - DCHECK(value.is(eax)); - - Operand mapped_location = GenerateMappedArgumentsLookup( - masm, receiver, name, ebx, edi, ¬in, &slow); - __ mov(mapped_location, value); - __ lea(ecx, mapped_location); - __ mov(edx, value); - __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs); - __ Ret(); - __ bind(¬in); - // The unmapped lookup expects that the parameter map is in ebx. - Operand unmapped_location = - GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow); - __ mov(unmapped_location, value); - __ lea(edi, unmapped_location); - __ mov(edx, value); - __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); - __ Ret(); - __ bind(&slow); - GenerateMiss(masm); -} - - static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { @@ -656,10 +560,28 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(ebx, &slow); + + + if (FLAG_vector_stores) { + // 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( + masm->isolate()->factory()->keyed_store_dummy_vector()); + int slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0)); + __ push(Immediate(Smi::FromInt(slot))); + __ push(Immediate(dummy_vector)); + } + Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( Code::ComputeHandlerFlags(Code::STORE_IC)); masm->isolate()->stub_cache()->GenerateProbe( masm, Code::STORE_IC, flags, false, receiver, key, ebx, no_reg); + + if (FLAG_vector_stores) { + __ pop(VectorStoreICDescriptor::VectorRegister()); + __ pop(VectorStoreICDescriptor::SlotRegister()); + } + // Cache miss. __ jmp(&miss); @@ -711,7 +633,7 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, } -void LoadIC::GenerateNormal(MacroAssembler* masm) { +void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { Register dictionary = eax; DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); @@ -726,33 +648,25 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // Dictionary load failed, go slow (but don't miss). __ bind(&slow); - GenerateRuntimeGetProperty(masm); + GenerateRuntimeGetProperty(masm, language_mode); } static void LoadIC_PushArgs(MacroAssembler* masm) { Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); - if (FLAG_vector_ics) { - Register slot = VectorLoadICDescriptor::SlotRegister(); - Register vector = VectorLoadICDescriptor::VectorRegister(); - DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && - !edi.is(vector)); - - __ pop(edi); - __ push(receiver); - __ push(name); - __ push(slot); - __ push(vector); - __ push(edi); - } else { - DCHECK(!ebx.is(receiver) && !ebx.is(name)); - __ pop(ebx); - __ push(receiver); - __ push(name); - __ push(ebx); - } + Register slot = LoadDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && + !edi.is(vector)); + + __ pop(edi); + __ push(receiver); + __ push(name); + __ push(slot); + __ push(vector); + __ push(edi); } @@ -764,12 +678,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // Return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); @@ -780,8 +695,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ push(name); __ push(ebx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong + : Runtime::kGetProperty, + 2, 1); } @@ -794,12 +711,13 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // Perform tail call to the entry. ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); - int arg_count = FLAG_vector_ics ? 4 : 2; + int arg_count = 4; __ TailCallExternalReference(ref, arg_count, 1); } -void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, + LanguageMode language_mode) { // Return address is on the stack. Register receiver = LoadDescriptor::ReceiverRegister(); Register name = LoadDescriptor::NameRegister(); @@ -810,8 +728,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { __ push(name); __ push(ebx); - // Perform tail call to the entry. - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); + // Do tail-call to runtime routine. + __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong + : Runtime::kKeyedGetProperty, + 2, 1); } @@ -962,7 +882,7 @@ void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); } -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X87 diff --git a/deps/v8/src/ic/x87/stub-cache-x87.cc b/deps/v8/src/ic/x87/stub-cache-x87.cc index be456ce95c..dfbba47e3f 100644 --- a/deps/v8/src/ic/x87/stub-cache-x87.cc +++ b/deps/v8/src/ic/x87/stub-cache-x87.cc @@ -61,8 +61,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, if (IC::ICUseVector(ic_kind)) { // The vector and slot were pushed onto the stack before starting the // probe, and need to be dropped before calling the handler. - __ pop(VectorLoadICDescriptor::VectorRegister()); - __ pop(VectorLoadICDescriptor::SlotRegister()); + __ pop(LoadWithVectorDescriptor::VectorRegister()); + __ pop(LoadDescriptor::SlotRegister()); } if (leave_frame) __ leave(); @@ -112,15 +112,14 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, if (IC::ICUseVector(ic_kind)) { // The vector and slot were pushed onto the stack before starting the // probe, and need to be dropped before calling the handler. - Register vector = VectorLoadICDescriptor::VectorRegister(); - Register slot = VectorLoadICDescriptor::SlotRegister(); + Register vector = LoadWithVectorDescriptor::VectorRegister(); + Register slot = LoadDescriptor::SlotRegister(); DCHECK(!offset.is(vector) && !offset.is(slot)); __ pop(vector); __ pop(slot); } - if (leave_frame) __ leave(); // Jump to the first instruction in the code stub. @@ -205,7 +204,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind, #undef __ -} -} // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_TARGET_ARCH_X87 |