summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2015-08-23 06:09:40 -0700
committerRod Vagg <rod@vagg.org>2015-09-06 21:38:01 +1000
commit9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch)
tree4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/ic
parent46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff)
downloadandroid-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')
-rw-r--r--deps/v8/src/ic/access-compiler.cc4
-rw-r--r--deps/v8/src/ic/access-compiler.h10
-rw-r--r--deps/v8/src/ic/arm/access-compiler-arm.cc4
-rw-r--r--deps/v8/src/ic/arm/handler-compiler-arm.cc4
-rw-r--r--deps/v8/src/ic/arm/ic-arm.cc222
-rw-r--r--deps/v8/src/ic/arm/ic-compiler-arm.cc4
-rw-r--r--deps/v8/src/ic/arm/stub-cache-arm.cc8
-rw-r--r--deps/v8/src/ic/arm64/access-compiler-arm64.cc4
-rw-r--r--deps/v8/src/ic/arm64/handler-compiler-arm64.cc4
-rw-r--r--deps/v8/src/ic/arm64/ic-arm64.cc263
-rw-r--r--deps/v8/src/ic/arm64/ic-compiler-arm64.cc4
-rw-r--r--deps/v8/src/ic/arm64/stub-cache-arm64.cc8
-rw-r--r--deps/v8/src/ic/call-optimization.cc4
-rw-r--r--deps/v8/src/ic/handler-compiler.cc37
-rw-r--r--deps/v8/src/ic/handler-compiler.h3
-rw-r--r--deps/v8/src/ic/ia32/access-compiler-ia32.cc4
-rw-r--r--deps/v8/src/ic/ia32/handler-compiler-ia32.cc11
-rw-r--r--deps/v8/src/ic/ia32/ic-compiler-ia32.cc4
-rw-r--r--deps/v8/src/ic/ia32/ic-ia32.cc224
-rw-r--r--deps/v8/src/ic/ia32/stub-cache-ia32.cc12
-rw-r--r--deps/v8/src/ic/ic-compiler.cc100
-rw-r--r--deps/v8/src/ic/ic-compiler.h10
-rw-r--r--deps/v8/src/ic/ic-inl.h61
-rw-r--r--deps/v8/src/ic/ic-state.cc30
-rw-r--r--deps/v8/src/ic/ic-state.h68
-rw-r--r--deps/v8/src/ic/ic.cc787
-rw-r--r--deps/v8/src/ic/ic.h158
-rw-r--r--deps/v8/src/ic/mips/access-compiler-mips.cc4
-rw-r--r--deps/v8/src/ic/mips/handler-compiler-mips.cc4
-rw-r--r--deps/v8/src/ic/mips/ic-compiler-mips.cc4
-rw-r--r--deps/v8/src/ic/mips/ic-mips.cc222
-rw-r--r--deps/v8/src/ic/mips/stub-cache-mips.cc8
-rw-r--r--deps/v8/src/ic/mips64/access-compiler-mips64.cc4
-rw-r--r--deps/v8/src/ic/mips64/handler-compiler-mips64.cc4
-rw-r--r--deps/v8/src/ic/mips64/ic-compiler-mips64.cc4
-rw-r--r--deps/v8/src/ic/mips64/ic-mips64.cc221
-rw-r--r--deps/v8/src/ic/mips64/stub-cache-mips64.cc14
-rw-r--r--deps/v8/src/ic/ppc/access-compiler-ppc.cc4
-rw-r--r--deps/v8/src/ic/ppc/handler-compiler-ppc.cc10
-rw-r--r--deps/v8/src/ic/ppc/ic-compiler-ppc.cc4
-rw-r--r--deps/v8/src/ic/ppc/ic-ppc.cc228
-rw-r--r--deps/v8/src/ic/ppc/stub-cache-ppc.cc8
-rw-r--r--deps/v8/src/ic/stub-cache.cc4
-rw-r--r--deps/v8/src/ic/x64/access-compiler-x64.cc4
-rw-r--r--deps/v8/src/ic/x64/handler-compiler-x64.cc4
-rw-r--r--deps/v8/src/ic/x64/ic-compiler-x64.cc4
-rw-r--r--deps/v8/src/ic/x64/ic-x64.cc226
-rw-r--r--deps/v8/src/ic/x64/stub-cache-x64.cc8
-rw-r--r--deps/v8/src/ic/x87/access-compiler-x87.cc4
-rw-r--r--deps/v8/src/ic/x87/handler-compiler-x87.cc11
-rw-r--r--deps/v8/src/ic/x87/ic-compiler-x87.cc4
-rw-r--r--deps/v8/src/ic/x87/ic-x87.cc224
-rw-r--r--deps/v8/src/ic/x87/stub-cache-x87.cc13
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, &notin, &slow);
- __ str(value, mapped_location);
- __ add(r6, r3, r5);
- __ mov(r9, value);
- __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
- __ Ret();
- __ bind(&notin);
- // 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, &notin, &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(&notin);
-
- // 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, &notin, &slow);
- __ mov(mapped_location, value);
- __ lea(ecx, mapped_location);
- __ mov(edx, value);
- __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
- __ Ret();
- __ bind(&notin);
- // 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, &notin, &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(&notin);
- // 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, &notin, &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(&notin);
- // 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, &notin, &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(&notin);
- // 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, &notin, &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(&notin);
- // 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, &notin, &slow);
- __ mov(mapped_location, value);
- __ lea(ecx, mapped_location);
- __ mov(edx, value);
- __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
- __ Ret();
- __ bind(&notin);
- // 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