Revert of Revert of [strong] Implement strong mode restrictions on property access...
authorconradw <conradw@chromium.org>
Thu, 18 Jun 2015 17:16:45 +0000 (10:16 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 18 Jun 2015 17:17:07 +0000 (17:17 +0000)
Reason for revert:
Issue was ultimately caused/fixed by https://codereview.chromium.org/1194673002/

Original issue's description:
> Revert of [strong] Implement strong mode restrictions on property access (patchset #23 id:460001 of https://codereview.chromium.org/1168093002/)
>
> Reason for revert:
> Speculative revert, maybe breaks GC-stress
>
> http://build.chromium.org/p/client.v8/builders/V8%20Linux64%20GC%20Stress%20-%20custom%20snapshot/builds/808
>
> Original issue's description:
> > [strong] Implement strong mode restrictions on property access
> >
> > Implements the strong mode proposal's restrictions on property access.
> >
> > To be fully explored in a followup: proxies, interceptors, access checks, load from super
> >
> > BUG=v8:3956
> > LOG=N
> >
> > Committed: https://crrev.com/85dbfb9a389e7b21bd2a63862202ee97fc5d7982
> > Cr-Commit-Position: refs/heads/master@{#29109}
>
> TBR=rossberg@chromium.org,mvstanton@chromium.org,mstarzinger@chromium.org,verwaest@chromium.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=v8:3956
>
> Committed: https://crrev.com/407657b706711fd5f8d417841e24b284886f3776
> Cr-Commit-Position: refs/heads/master@{#29115}

TBR=rossberg@chromium.org,mvstanton@chromium.org,mstarzinger@chromium.org,verwaest@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1185343005

Cr-Commit-Position: refs/heads/master@{#29122}

82 files changed:
src/arm/code-stubs-arm.cc
src/arm/full-codegen-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm64/code-stubs-arm64.cc
src/arm64/full-codegen-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/builtins.cc
src/builtins.h
src/code-factory.cc
src/code-factory.h
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/code-stubs.h
src/compiler/ast-graph-builder.cc
src/compiler/js-generic-lowering.cc
src/compiler/js-operator.cc
src/compiler/js-operator.h
src/compiler/js-typed-lowering.cc
src/full-codegen.cc
src/full-codegen.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/code-stubs-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ic/arm/handler-compiler-arm.cc
src/ic/arm/ic-arm.cc
src/ic/arm64/handler-compiler-arm64.cc
src/ic/arm64/ic-arm64.cc
src/ic/handler-compiler.cc
src/ic/handler-compiler.h
src/ic/ia32/handler-compiler-ia32.cc
src/ic/ia32/ic-ia32.cc
src/ic/ic-compiler.cc
src/ic/ic-compiler.h
src/ic/ic-inl.h
src/ic/ic-state.h
src/ic/ic.cc
src/ic/ic.h
src/ic/mips/handler-compiler-mips.cc
src/ic/mips/ic-mips.cc
src/ic/mips64/handler-compiler-mips64.cc
src/ic/mips64/ic-mips64.cc
src/ic/ppc/handler-compiler-ppc.cc
src/ic/ppc/ic-ppc.cc
src/ic/x64/handler-compiler-x64.cc
src/ic/x64/ic-x64.cc
src/ic/x87/handler-compiler-x87.cc
src/ic/x87/ic-x87.cc
src/messages.h
src/mips/code-stubs-mips.cc
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips64/code-stubs-mips64.cc
src/mips64/full-codegen-mips64.cc
src/mips64/lithium-codegen-mips64.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/ppc/code-stubs-ppc.cc
src/ppc/full-codegen-ppc.cc
src/ppc/lithium-codegen-ppc.cc
src/runtime/runtime-classes.cc
src/runtime/runtime-debug.cc
src/runtime/runtime-object.cc
src/runtime/runtime.h
src/x64/code-stubs-x64.cc
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x87/code-stubs-x87.cc
src/x87/full-codegen-x87.cc
src/x87/lithium-codegen-x87.cc
test/cctest/test-api.cc
test/mjsunit/strong/functions.js
test/mjsunit/strong/load-builtins.js [new file with mode: 0644]
test/mjsunit/strong/load-element-mutate-backing-store.js [new file with mode: 0644]
test/mjsunit/strong/load-element.js [new file with mode: 0644]
test/mjsunit/strong/load-property-mutate-backing-store.js [new file with mode: 0644]
test/mjsunit/strong/load-property.js [new file with mode: 0644]
test/unittests/compiler/js-type-feedback-unittest.cc
test/unittests/compiler/js-typed-lowering-unittest.cc

index 5adf670..b0ef706 100644 (file)
@@ -4372,7 +4372,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4582,7 +4582,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ b(ne, &try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index f5b90b6..2464157 100644 (file)
@@ -2242,7 +2242,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
       __ mov(LoadDescriptor::SlotRegister(),
              Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(r1, r0);
       __ str(r1, MemOperand(sp, 2 * kPointerSize));
@@ -2423,7 +2423,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ mov(LoadDescriptor::NameRegister(), Operand(key->value()));
   __ mov(LoadDescriptor::SlotRegister(),
          Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2435,13 +2435,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ mov(LoadDescriptor::SlotRegister(),
          Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2450,9 +2451,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2998,6 +3000,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
   __ Push(scratch);
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -3005,7 +3008,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ str(r0, MemOperand(sp, kPointerSize));
@@ -3058,6 +3062,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
   __ Push(scratch);
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -3065,7 +3070,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ str(r0, MemOperand(sp, kPointerSize));
index 8f6cdd3..a5639f8 100644 (file)
@@ -2952,7 +2952,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -3048,9 +3048,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   // Name is always in r2.
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -3357,9 +3358,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
index cfce619..52549c0 100644 (file)
@@ -4494,7 +4494,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4703,7 +4703,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex,
                    &try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ Bind(&try_poly_name);
index 2cf7142..ff47e34 100644 (file)
@@ -2091,7 +2091,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ Mov(LoadDescriptor::NameRegister(), Operand(key->value()));
   __ Mov(LoadDescriptor::SlotRegister(),
          SmiFromSlot(prop->PropertyFeedbackSlot()));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2103,14 +2103,15 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
   // Call keyed load IC. It has arguments key and receiver in x0 and x1.
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ Mov(LoadDescriptor::SlotRegister(),
          SmiFromSlot(prop->PropertyFeedbackSlot()));
   CallIC(ic);
@@ -2119,9 +2120,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2683,14 +2685,15 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   __ Peek(scratch, kPointerSize);
   __ Push(x0, scratch);
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
   //  - this (receiver)
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
-  //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ Poke(x0, kPointerSize);
@@ -2743,6 +2746,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   __ Peek(scratch, kPointerSize);
   __ Push(x0, scratch);
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2750,7 +2754,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ Poke(x0, kPointerSize);
@@ -5198,7 +5203,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ Peek(load_name, 2 * kPointerSize);
       __ Mov(LoadDescriptor::SlotRegister(),
              SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ Mov(x1, x0);
       __ Poke(x1, 2 * kPointerSize);
index ec6e3c7..8275d8c 100644 (file)
@@ -3306,7 +3306,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -3576,9 +3576,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 
   DCHECK(ToRegister(instr->result()).Is(x0));
@@ -3632,10 +3632,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   __ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 
   DCHECK(ToRegister(instr->result()).is(x0));
index 506492f..fe58a09 100644 (file)
@@ -1278,17 +1278,12 @@ static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
 
 
 static void Generate_LoadIC_Slow(MacroAssembler* masm) {
-  LoadIC::GenerateRuntimeGetProperty(masm);
-}
-
-
-static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
-  KeyedLoadIC::GenerateInitialize(masm);
+  NamedLoadHandlerCompiler::GenerateSlow(masm);
 }
 
 
 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
-  KeyedLoadIC::GenerateRuntimeGetProperty(masm);
+  ElementHandlerCompiler::GenerateLoadSlow(masm);
 }
 
 
@@ -1298,7 +1293,12 @@ static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
 
 
 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
-  KeyedLoadIC::GenerateMegamorphic(masm);
+  KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
+}
+
+
+static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
+  KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
 }
 
 
index 7d0d6c2..e973c80 100644 (file)
@@ -86,9 +86,11 @@ enum BuiltinExtraArguments {
   V(StoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)                   \
   V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)              \
   V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, kNoExtraICState)           \
-  V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED, kNoExtraICState)   \
   V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState)    \
                                                                              \
+  V(KeyedLoadIC_Megamorphic_Strong, KEYED_LOAD_IC, MEGAMORPHIC,              \
+    LoadICState::kStrongModeState)                                           \
+                                                                             \
   V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC,                          \
     StoreICState::kStrictModeState)                                          \
                                                                              \
@@ -104,7 +106,6 @@ enum BuiltinExtraArguments {
   V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC,            \
     StoreICState::kStrictModeState)                                          \
                                                                              \
-  /* Uses KeyedLoadIC_Initialize; must be after in list. */                  \
   V(FunctionCall, BUILTIN, UNINITIALIZED, kNoExtraICState)                   \
   V(FunctionApply, BUILTIN, UNINITIALIZED, kNoExtraICState)                  \
   V(ReflectApply, BUILTIN, UNINITIALIZED, kNoExtraICState)                   \
@@ -126,13 +127,13 @@ enum BuiltinExtraArguments {
   CODE_AGE_LIST_WITH_ARG(DECLARE_CODE_AGE_BUILTIN, V)
 
 // Define list of builtin handlers implemented in assembly.
-#define BUILTIN_LIST_H(V)                                               \
-  V(LoadIC_Slow,                    LOAD_IC)                            \
-  V(KeyedLoadIC_Slow,               KEYED_LOAD_IC)                      \
-  V(StoreIC_Slow,                   STORE_IC)                           \
-  V(KeyedStoreIC_Slow,              KEYED_STORE_IC)                     \
-  V(LoadIC_Normal,                  LOAD_IC)                            \
-  V(StoreIC_Normal,                 STORE_IC)
+#define BUILTIN_LIST_H(V)                 \
+  V(LoadIC_Slow,          LOAD_IC)        \
+  V(KeyedLoadIC_Slow,     KEYED_LOAD_IC)  \
+  V(StoreIC_Slow,         STORE_IC)       \
+  V(KeyedStoreIC_Slow,    KEYED_STORE_IC) \
+  V(LoadIC_Normal,        LOAD_IC)        \
+  V(StoreIC_Normal,       STORE_IC)
 
 // Define list of builtins used by the debugger implemented in assembly.
 #define BUILTIN_LIST_DEBUG_A(V)                                               \
index fc7ea4a..8997747 100644 (file)
@@ -13,35 +13,44 @@ namespace internal {
 
 
 // static
-Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) {
+Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode,
+                             LanguageMode language_mode) {
   return Callable(
-      LoadIC::initialize_stub(isolate, LoadICState(mode).GetExtraICState()),
+      LoadIC::initialize_stub(
+          isolate, LoadICState(mode, language_mode).GetExtraICState()),
       LoadDescriptor(isolate));
 }
 
 
 // static
 Callable CodeFactory::LoadICInOptimizedCode(
-    Isolate* isolate, ContextualMode mode,
+    Isolate* isolate, ContextualMode mode, LanguageMode language_mode,
     InlineCacheState initialization_state) {
   auto code = LoadIC::initialize_stub_in_optimized_code(
-      isolate, LoadICState(mode).GetExtraICState(), initialization_state);
+      isolate, LoadICState(mode, language_mode).GetExtraICState(),
+      initialization_state);
   return Callable(code, LoadWithVectorDescriptor(isolate));
 }
 
 
 // static
-Callable CodeFactory::KeyedLoadIC(Isolate* isolate) {
-  return Callable(KeyedLoadIC::initialize_stub(isolate),
+Callable CodeFactory::KeyedLoadIC(Isolate* isolate,
+                                  LanguageMode language_mode) {
+  ExtraICState state =
+      is_strong(language_mode) ? LoadICState::kStrongModeState : 0;
+  return Callable(KeyedLoadIC::initialize_stub(isolate, state),
                   LoadDescriptor(isolate));
 }
 
 
 // static
 Callable CodeFactory::KeyedLoadICInOptimizedCode(
-    Isolate* isolate, InlineCacheState initialization_state) {
+    Isolate* isolate, LanguageMode language_mode,
+    InlineCacheState initialization_state) {
+  ExtraICState state =
+      is_strong(language_mode) ? LoadICState::kStrongModeState : 0;
   auto code = KeyedLoadIC::initialize_stub_in_optimized_code(
-      isolate, initialization_state);
+      isolate, initialization_state, state);
   if (initialization_state != MEGAMORPHIC) {
     return Callable(code, LoadWithVectorDescriptor(isolate));
   }
index e26fc09..c043f55 100644 (file)
@@ -32,12 +32,15 @@ class Callable final BASE_EMBEDDED {
 class CodeFactory final {
  public:
   // Initial states for ICs.
-  static Callable LoadIC(Isolate* isolate, ContextualMode mode);
+  static Callable LoadIC(Isolate* isolate, ContextualMode mode,
+                         LanguageMode language_mode);
   static Callable LoadICInOptimizedCode(Isolate* isolate, ContextualMode mode,
+                                        LanguageMode language_mode,
                                         InlineCacheState initialization_state);
-  static Callable KeyedLoadIC(Isolate* isolate);
+  static Callable KeyedLoadIC(Isolate* isolate, LanguageMode language_mode);
   static Callable KeyedLoadICInOptimizedCode(
-      Isolate* isolate, InlineCacheState initialization_state);
+      Isolate* isolate, LanguageMode language_mode,
+      InlineCacheState initialization_state);
   static Callable CallIC(Isolate* isolate, int argc,
                          CallICState::CallType call_type);
   static Callable CallICInOptimizedCode(Isolate* isolate, int argc,
index 4573da1..eeeef2c 100644 (file)
@@ -62,8 +62,7 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
   HContext* context() { return context_; }
   Isolate* isolate() { return info_->isolate(); }
 
-  HLoadNamedField* BuildLoadNamedField(HValue* object,
-                                       FieldIndex index);
+  HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index);
   void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
                             Representation representation,
                             bool transition_to_field);
@@ -1901,7 +1900,8 @@ HValue* CodeStubGraphBuilder<LoadDictionaryElementStub>::BuildCodeStub() {
 
   HValue* hash = BuildElementIndexHash(key);
 
-  return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
+  return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
+                                             casted_stub()->language_mode());
 }
 
 
@@ -2015,7 +2015,6 @@ void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildExternalElementLoad(
 HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
   HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
   HValue* key = GetParameter(LoadDescriptor::kNameIndex);
-
   // Split into a smi/integer case and unique string case.
   HIfContinuation index_name_split_continuation(graph()->CreateBasicBlock(),
                                                 graph()->CreateBasicBlock());
@@ -2059,7 +2058,8 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
 
       HValue* hash = BuildElementIndexHash(key);
 
-      Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash));
+      Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
+                                               casted_stub()->language_mode()));
     }
     kind_if.Else();
 
@@ -2137,10 +2137,8 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
 
       hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift));
 
-      HValue* value = BuildUncheckedDictionaryElementLoad(receiver,
-                                                          properties,
-                                                          key,
-                                                          hash);
+      HValue* value = BuildUncheckedDictionaryElementLoad(
+          receiver, properties, key, hash, casted_stub()->language_mode());
       Push(value);
     }
     if_dict_properties.Else();
@@ -2215,10 +2213,11 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
       inline_or_runtime.Else();
       {
         // KeyedLookupCache miss; call runtime.
-        Add<HPushArguments>(receiver, key);
+        Add<HPushArguments>(receiver, key,
+                            Add<HConstant>(casted_stub()->language_mode()));
         Push(Add<HCallRuntime>(
             isolate()->factory()->empty_string(),
-            Runtime::FunctionForId(Runtime::kKeyedGetProperty), 2));
+            Runtime::FunctionForId(Runtime::kKeyedGetProperty), 3));
       }
       inline_or_runtime.End();
     }
index c007199..2cf4954 100644 (file)
@@ -123,7 +123,6 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
   // Create the code object.
   CodeDesc desc;
   masm.GetCode(&desc);
-
   // Copy the generated code into a heap object.
   Code::Flags flags = Code::ComputeFlags(
       GetCodeKind(),
index 515f2e5..ac373f0 100644 (file)
@@ -2114,24 +2114,37 @@ class StringCharAtGenerator {
 
 class LoadDictionaryElementStub : public HydrogenCodeStub {
  public:
-  explicit LoadDictionaryElementStub(Isolate* isolate)
-      : HydrogenCodeStub(isolate) {}
+  explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
+      : HydrogenCodeStub(isolate) {
+    minor_key_ = state.GetExtraICState();
+  }
 
   CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
     return LoadWithVectorDescriptor(isolate());
   }
 
+  LanguageMode language_mode() const {
+    return LoadICState::GetLanguageMode(MinorKey());
+  }
+
   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
 };
 
 
 class KeyedLoadGenericStub : public HydrogenCodeStub {
  public:
-  explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
+  explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
+      : HydrogenCodeStub(isolate) {
+    minor_key_ = state.GetExtraICState();
+  }
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
   InlineCacheState GetICState() const override { return GENERIC; }
 
+  LanguageMode language_mode() const {
+    return LoadICState::GetLanguageMode(MinorKey());
+  }
+
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
 
   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
@@ -2153,7 +2166,7 @@ class LoadICTrampolineStub : public PlatformCodeStub {
     return static_cast<ExtraICState>(minor_key_);
   }
 
- private:
+ protected:
   LoadICState state() const {
     return LoadICState(static_cast<ExtraICState>(minor_key_));
   }
@@ -2165,8 +2178,8 @@ class LoadICTrampolineStub : public PlatformCodeStub {
 
 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
  public:
-  explicit KeyedLoadICTrampolineStub(Isolate* isolate)
-      : LoadICTrampolineStub(isolate, LoadICState(0)) {}
+  explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
+      : LoadICTrampolineStub(isolate, state) {}
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
 
@@ -2272,12 +2285,18 @@ class LoadICStub : public PlatformCodeStub {
 
 class KeyedLoadICStub : public PlatformCodeStub {
  public:
-  explicit KeyedLoadICStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
+  explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
+      : PlatformCodeStub(isolate) {
+    minor_key_ = state.GetExtraICState();
+  }
 
   void GenerateForTrampoline(MacroAssembler* masm);
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
   InlineCacheState GetICState() const final { return DEFAULT; }
+  ExtraICState GetExtraICState() const final {
+    return static_cast<ExtraICState>(minor_key_);
+  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
@@ -2321,6 +2340,9 @@ class VectorKeyedStoreICStub : public PlatformCodeStub {
 
   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
   InlineCacheState GetICState() const final { return DEFAULT; }
+  virtual ExtraICState GetExtraICState() const final {
+    return static_cast<ExtraICState>(minor_key_);
+  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
index 159536c..f967a97 100644 (file)
@@ -3459,7 +3459,7 @@ static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node,
 
 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
                                       const ResolvedFeedbackSlot& feedback) {
-  const Operator* op = javascript()->LoadProperty(feedback);
+  const Operator* op = javascript()->LoadProperty(feedback, language_mode());
   return Record(js_type_feedback_,
                 NewNode(op, object, key, GetFeedbackVector()), feedback.slot());
 }
@@ -3468,8 +3468,8 @@ Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
 Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
                                       const ResolvedFeedbackSlot& feedback,
                                       ContextualMode mode) {
-  const Operator* op =
-      javascript()->LoadNamed(MakeUnique(name), feedback, mode);
+  const Operator* op = javascript()->LoadNamed(MakeUnique(name), feedback,
+                                               language_mode(), mode);
   return Record(js_type_feedback_, NewNode(op, object, GetFeedbackVector()),
                 feedback.slot());
 }
@@ -3494,8 +3494,9 @@ Node* AstGraphBuilder::BuildNamedSuperLoad(
     Node* receiver, Node* home_object, Handle<Name> name,
     const ResolvedFeedbackSlot& feedback) {
   Node* name_node = jsgraph()->Constant(name);
-  const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 3);
-  Node* value = NewNode(op, receiver, home_object, name_node);
+  Node* language = jsgraph()->Constant(language_mode());
+  const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 4);
+  Node* value = NewNode(op, receiver, home_object, name_node, language);
   return Record(js_type_feedback_, value, feedback.slot());
 }
 
@@ -3503,9 +3504,10 @@ Node* AstGraphBuilder::BuildNamedSuperLoad(
 Node* AstGraphBuilder::BuildKeyedSuperLoad(
     Node* receiver, Node* home_object, Node* key,
     const ResolvedFeedbackSlot& feedback) {
+  Node* language = jsgraph()->Constant(language_mode());
   const Operator* op =
-      javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
-  Node* value = NewNode(op, receiver, home_object, key);
+      javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
+  Node* value = NewNode(op, receiver, home_object, key, language);
   return Record(js_type_feedback_, value, feedback.slot());
 }
 
index 9132a39..f3863d6 100644 (file)
@@ -314,8 +314,8 @@ void JSGenericLowering::LowerJSToObject(Node* node) {
 void JSGenericLowering::LowerJSLoadProperty(Node* node) {
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   const LoadPropertyParameters& p = LoadPropertyParametersOf(node->op());
-  Callable callable =
-      CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
+  Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(
+      isolate(), p.language_mode(), UNINITIALIZED);
   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
   ReplaceWithStubCall(node, callable, flags);
 }
@@ -325,7 +325,7 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) {
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
   Callable callable = CodeFactory::LoadICInOptimizedCode(
-      isolate(), p.contextual_mode(), UNINITIALIZED);
+      isolate(), p.contextual_mode(), p.language_mode(), UNINITIALIZED);
   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
   ReplaceWithStubCall(node, callable, flags);
index 83bf557..8a2c6fe 100644 (file)
@@ -190,6 +190,7 @@ size_t hash_value(ResolvedFeedbackSlot const& p) {
 bool operator==(LoadNamedParameters const& lhs,
                 LoadNamedParameters const& rhs) {
   return lhs.name() == rhs.name() &&
+         lhs.language_mode() == rhs.language_mode() &&
          lhs.contextual_mode() == rhs.contextual_mode() &&
          lhs.feedback() == rhs.feedback();
 }
@@ -202,24 +203,26 @@ bool operator!=(LoadNamedParameters const& lhs,
 
 
 size_t hash_value(LoadNamedParameters const& p) {
-  return base::hash_combine(p.name(), p.contextual_mode(), p.feedback());
+  return base::hash_combine(p.name(), p.language_mode(), p.contextual_mode(),
+                            p.feedback());
 }
 
 
 std::ostream& operator<<(std::ostream& os, LoadNamedParameters const& p) {
-  return os << Brief(*p.name().handle()) << ", " << p.contextual_mode();
+  return os << Brief(*p.name().handle()) << ", " << p.language_mode() << ", "
+            << p.contextual_mode();
 }
 
 
 std::ostream& operator<<(std::ostream& os, LoadPropertyParameters const& p) {
-  // Nothing special to print.
-  return os;
+  return os << p.language_mode();
 }
 
 
 bool operator==(LoadPropertyParameters const& lhs,
                 LoadPropertyParameters const& rhs) {
-  return lhs.feedback() == rhs.feedback();
+  return lhs.language_mode() == rhs.language_mode() &&
+         lhs.feedback() == rhs.feedback();
 }
 
 
@@ -236,7 +239,7 @@ const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op) {
 
 
 size_t hash_value(LoadPropertyParameters const& p) {
-  return hash_value(p.feedback());
+  return base::hash_combine(p.language_mode(), p.feedback());
 }
 
 
@@ -459,8 +462,9 @@ const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
 
 const Operator* JSOperatorBuilder::LoadNamed(
     const Unique<Name>& name, const ResolvedFeedbackSlot& feedback,
-    ContextualMode contextual_mode) {
-  LoadNamedParameters parameters(name, feedback, contextual_mode);
+    LanguageMode language_mode, ContextualMode contextual_mode) {
+  LoadNamedParameters parameters(name, feedback, language_mode,
+                                 contextual_mode);
   return new (zone()) Operator1<LoadNamedParameters>(   // --
       IrOpcode::kJSLoadNamed, Operator::kNoProperties,  // opcode
       "JSLoadNamed",                                    // name
@@ -470,8 +474,8 @@ const Operator* JSOperatorBuilder::LoadNamed(
 
 
 const Operator* JSOperatorBuilder::LoadProperty(
-    const ResolvedFeedbackSlot& feedback) {
-  LoadPropertyParameters parameters(feedback);
+    const ResolvedFeedbackSlot& feedback, LanguageMode language_mode) {
+  LoadPropertyParameters parameters(feedback, language_mode);
   return new (zone()) Operator1<LoadPropertyParameters>(   // --
       IrOpcode::kJSLoadProperty, Operator::kNoProperties,  // opcode
       "JSLoadProperty",                                    // name
index e9545c9..40c5f7d 100644 (file)
@@ -223,10 +223,15 @@ class LoadNamedParameters final {
  public:
   LoadNamedParameters(const Unique<Name>& name,
                       const ResolvedFeedbackSlot& feedback,
+                      LanguageMode language_mode,
                       ContextualMode contextual_mode)
-      : name_(name), feedback_(feedback), contextual_mode_(contextual_mode) {}
+      : name_(name),
+        feedback_(feedback),
+        language_mode_(language_mode),
+        contextual_mode_(contextual_mode) {}
 
   const Unique<Name>& name() const { return name_; }
+  LanguageMode language_mode() const { return language_mode_; }
   ContextualMode contextual_mode() const { return contextual_mode_; }
 
   const ResolvedFeedbackSlot& feedback() const { return feedback_; }
@@ -234,6 +239,7 @@ class LoadNamedParameters final {
  private:
   const Unique<Name> name_;
   const ResolvedFeedbackSlot feedback_;
+  const LanguageMode language_mode_;
   const ContextualMode contextual_mode_;
 };
 
@@ -251,13 +257,17 @@ const LoadNamedParameters& LoadNamedParametersOf(const Operator* op);
 // used as a parameter by JSLoadProperty operators.
 class LoadPropertyParameters final {
  public:
-  explicit LoadPropertyParameters(const ResolvedFeedbackSlot& feedback)
-      : feedback_(feedback) {}
+  explicit LoadPropertyParameters(const ResolvedFeedbackSlot& feedback,
+                                  LanguageMode language_mode)
+      : feedback_(feedback), language_mode_(language_mode) {}
 
   const ResolvedFeedbackSlot& feedback() const { return feedback_; }
 
+  LanguageMode language_mode() const { return language_mode_; }
+
  private:
   const ResolvedFeedbackSlot feedback_;
+  const LanguageMode language_mode_;
 };
 
 bool operator==(LoadPropertyParameters const&, LoadPropertyParameters const&);
@@ -368,9 +378,11 @@ class JSOperatorBuilder final : public ZoneObject {
 
   const Operator* CallConstruct(int arguments);
 
-  const Operator* LoadProperty(const ResolvedFeedbackSlot& feedback);
+  const Operator* LoadProperty(const ResolvedFeedbackSlot& feedback,
+                               LanguageMode language_mode);
   const Operator* LoadNamed(const Unique<Name>& name,
                             const ResolvedFeedbackSlot& feedback,
+                            LanguageMode language_mode,
                             ContextualMode contextual_mode = NOT_CONTEXTUAL);
 
   const Operator* StoreProperty(LanguageMode language_mode);
index 94fae66..4a5ab67 100644 (file)
@@ -1025,8 +1025,8 @@ Reduction JSTypedLowering::ReduceJSLoadDynamicGlobal(Node* node) {
       javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true), context,
       context, effect);
   Node* fast = graph()->NewNode(
-      javascript()->LoadNamed(name, access.feedback(), access.mode()), global,
-      vector, context, state1, state2, global, check_true);
+      javascript()->LoadNamed(name, access.feedback(), SLOPPY, access.mode()),
+      global, vector, context, state1, state2, global, check_true);
 
   // Slow case, because variable potentially shadowed. Perform dynamic lookup.
   uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired;
index f1b3904..5860da8 100644 (file)
@@ -469,8 +469,10 @@ void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
 
 
 void FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode,
+                                   LanguageMode language_mode,
                                    TypeFeedbackId id) {
-  Handle<Code> ic = CodeFactory::LoadIC(isolate(), contextual_mode).code();
+  Handle<Code> ic =
+      CodeFactory::LoadIC(isolate(), contextual_mode, language_mode).code();
   CallIC(ic, id);
 }
 
index 4492434..3cc400a 100644 (file)
@@ -683,7 +683,7 @@ class FullCodeGenerator: public AstVisitor {
   void CallIC(Handle<Code> code,
               TypeFeedbackId id = TypeFeedbackId::None());
 
-  void CallLoadIC(ContextualMode mode,
+  void CallLoadIC(ContextualMode mode, LanguageMode language_mode = SLOPPY,
                   TypeFeedbackId id = TypeFeedbackId::None());
   void CallGlobalLoadIC(Handle<String> name);
   void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
index 15aa385..bdb4a6b 100644 (file)
@@ -6392,8 +6392,9 @@ class HLoadNamedField final : public HTemplateInstruction<2> {
 
 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadNamedGeneric, HValue*,
-                                              Handle<Object>, InlineCacheState);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
+                                              Handle<Object>, LanguageMode,
+                                              InlineCacheState);
 
   HValue* context() const { return OperandAt(0); }
   HValue* object() const { return OperandAt(1); }
@@ -6421,11 +6422,15 @@ class HLoadNamedGeneric final : public HTemplateInstruction<2> {
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
 
+  LanguageMode language_mode() const { return language_mode_; }
+
  private:
   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name,
+                    LanguageMode language_mode,
                     InlineCacheState initialization_state)
       : name_(name),
         slot_(FeedbackVectorICSlot::Invalid()),
+        language_mode_(language_mode),
         initialization_state_(initialization_state) {
     SetOperandAt(0, context);
     SetOperandAt(1, object);
@@ -6436,6 +6441,7 @@ class HLoadNamedGeneric final : public HTemplateInstruction<2> {
   Handle<Object> name_;
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorICSlot slot_;
+  LanguageMode language_mode_;
   InlineCacheState initialization_state_;
 };
 
@@ -6675,8 +6681,9 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
 
 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadKeyedGeneric, HValue*,
-                                              HValue*, InlineCacheState);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
+                                              HValue*, LanguageMode,
+                                              InlineCacheState);
   HValue* object() const { return OperandAt(0); }
   HValue* key() const { return OperandAt(1); }
   HValue* context() const { return OperandAt(2); }
@@ -6708,11 +6715,15 @@ class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
 
+  LanguageMode language_mode() const { return language_mode_; }
+
  private:
   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
+                    LanguageMode language_mode,
                     InlineCacheState initialization_state)
       : slot_(FeedbackVectorICSlot::Invalid()),
-        initialization_state_(initialization_state) {
+        initialization_state_(initialization_state),
+        language_mode_(language_mode) {
     set_representation(Representation::Tagged());
     SetOperandAt(0, obj);
     SetOperandAt(1, key);
@@ -6723,6 +6734,7 @@ class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorICSlot slot_;
   InlineCacheState initialization_state_;
+  LanguageMode language_mode_;
 };
 
 
index 2a0011f..d1959bb 100644 (file)
@@ -683,6 +683,11 @@ HConstant* HGraph::GetConstantMinus1() {
 }
 
 
+HConstant* HGraph::GetConstantBool(bool value) {
+  return value ? GetConstantTrue() : GetConstantFalse();
+}
+
+
 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
 HConstant* HGraph::GetConstant##Name() {                                       \
   if (!constant_##name##_.is_set()) {                                          \
@@ -1667,10 +1672,9 @@ HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
 }
 
 
-HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
-                                                           HValue* elements,
-                                                           HValue* key,
-                                                           HValue* hash) {
+HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
+    HValue* receiver, HValue* elements, HValue* key, HValue* hash,
+    LanguageMode language_mode) {
   HValue* capacity =
       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
                       nullptr, FAST_ELEMENTS);
@@ -1712,10 +1716,10 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
   {
     // element == undefined means "not found". Call the runtime.
     // TODO(jkummerow): walk the prototype chain instead.
-    Add<HPushArguments>(receiver, key);
+    Add<HPushArguments>(receiver, key, Add<HConstant>(language_mode));
     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
-                           2));
+                           3));
   }
   if_undefined.Else();
   {
@@ -1772,10 +1776,10 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
     result_index->ClearFlag(HValue::kCanOverflow);
     Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
     details_compare.Else();
-    Add<HPushArguments>(receiver, key);
+    Add<HPushArguments>(receiver, key, Add<HConstant>(language_mode));
     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
-                           2));
+                           3));
     details_compare.End();
 
     found_key_match.Else();
@@ -6223,7 +6227,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   if (IsFound()) return IsLoad() || !IsReadOnly();
   if (IsIntegerIndexedExotic()) return false;
   if (!LookupInPrototypes()) return false;
-  if (IsLoad()) return true;
+  if (IsLoad()) return !is_strong(builder_->function_language_mode());
 
   if (IsAccessorConstant()) return true;
   LookupTransition(*map_, *name_, NONE);
@@ -7041,14 +7045,14 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
       // use a generic Keyed Load if we are using the type vector, because
       // it has to share information with full code.
       HConstant* key = Add<HConstant>(name);
-      HLoadKeyedGeneric* result =
-          New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
+      HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
+          object, key, function_language_mode(), PREMONOMORPHIC);
       result->SetVectorAndSlot(vector, slot);
       return result;
     }
 
-    HLoadNamedGeneric* result =
-        New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
+    HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
+        object, name, function_language_mode(), PREMONOMORPHIC);
     result->SetVectorAndSlot(vector, slot);
     return result;
   } else {
@@ -7067,8 +7071,8 @@ HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
     HValue* value) {
   if (access_type == LOAD) {
     InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
-    HLoadKeyedGeneric* result =
-        New<HLoadKeyedGeneric>(object, key, initial_state);
+    HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
+        object, key, function_language_mode(), initial_state);
     // HLoadKeyedGeneric with vector ics benefits from being encoded as
     // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
     if (initial_state != MEGAMORPHIC) {
index 48e333f..acde9f0 100644 (file)
@@ -331,6 +331,7 @@ class HGraph final : public ZoneObject {
   HConstant* GetConstantMinus1();
   HConstant* GetConstantTrue();
   HConstant* GetConstantFalse();
+  HConstant* GetConstantBool(bool value);
   HConstant* GetConstantHole();
   HConstant* GetConstantNull();
   HConstant* GetInvalidContext();
@@ -1352,9 +1353,9 @@ class HGraphBuilder {
                                     HValue* key);
 
   HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
-                                              HValue* elements,
-                                              HValue* key,
-                                              HValue* hash);
+                                              HValue* elements, HValue* key,
+                                              HValue* hash,
+                                              LanguageMode language_mode);
 
   HValue* BuildRegExpConstructResult(HValue* length,
                                      HValue* index,
index 7435ccd..8ae0fed 100644 (file)
@@ -4430,7 +4430,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4634,7 +4634,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ j(not_equal, &try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index f27dd21..1fd2cb9 100644 (file)
@@ -2166,7 +2166,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ mov(load_receiver, Operand(esp, kPointerSize));
       __ mov(LoadDescriptor::SlotRegister(),
              Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(edi, eax);
       __ mov(Operand(esp, 2 * kPointerSize), edi);
@@ -2335,7 +2335,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
   __ mov(LoadDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2347,13 +2347,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ push(Immediate(key->value()));
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ push(Immediate(Smi::FromInt(language_mode())));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ mov(LoadDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2362,9 +2363,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ push(Immediate(Smi::FromInt(language_mode())));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2894,13 +2896,15 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   __ push(eax);
   __ push(Operand(esp, kPointerSize * 2));
   __ push(Immediate(key->value()));
+  __ push(Immediate(Smi::FromInt(language_mode())));
   // Stack here:
   //  - home_object
   //  - this (receiver)
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2950,13 +2954,15 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   __ push(eax);
   __ push(Operand(esp, kPointerSize * 2));
   VisitForStackValue(prop->key());
+  __ push(Immediate(Smi::FromInt(language_mode())));
   // Stack here:
   //  - home_object
   //  - this (receiver)
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
index ba601db..3348c9f 100644 (file)
@@ -2836,7 +2836,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -2952,9 +2952,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
 
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3196,9 +3197,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 6af65e2..86eddde 100644 (file)
@@ -16,6 +16,30 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the load without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the load without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index 3ecdc31..e61555a 100644 (file)
@@ -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.
@@ -278,7 +284,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -313,13 +319,17 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
 
   __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
   __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -341,16 +351,21 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
 
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 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;
@@ -374,7 +389,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();
 
@@ -396,7 +412,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   __ bind(&slow);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4,
                       r3);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
index 3986c0e..5d1c8e2 100644 (file)
@@ -267,6 +267,30 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
 }
 
 
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the load without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the load without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index e0bf48b..e513845 100644 (file)
@@ -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.
@@ -272,7 +278,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ Bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -296,10 +302,15 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -324,10 +335,15 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -335,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));
 
@@ -351,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();
@@ -422,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;
 
@@ -435,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);
+  GenerateSlow(masm);
 
   __ Bind(&check_name);
   GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
index 04b8fb0..99c9c15 100644 (file)
@@ -537,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;
@@ -553,8 +554,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();
@@ -567,7 +570,9 @@ 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 : 0);
+        cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode();
       }
     }
 
index 077db92..66fdf56 100644 (file)
@@ -146,6 +146,8 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
   static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
                                              Handle<Map> map);
 
+  static void GenerateSlow(MacroAssembler* masm);
+
   static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
                                     Register receiver, Register holder,
                                     int accessor_index, int expected_arguments,
@@ -290,8 +292,10 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
   virtual ~ElementHandlerCompiler() {}
 
   void CompileElementHandlers(MapHandleList* receiver_maps,
-                              CodeHandleList* handlers);
+                              CodeHandleList* handlers,
+                              LanguageMode language_mode);
 
+  static void GenerateLoadSlow(MacroAssembler* masm);
   static void GenerateStoreSlow(MacroAssembler* masm);
 };
 }
index 8f5200a..57a478e 100644 (file)
@@ -16,6 +16,39 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+static void LoadIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = LoadDescriptor::ReceiverRegister();
+  Register name = LoadDescriptor::NameRegister();
+
+  DCHECK(!ebx.is(receiver) && !ebx.is(name));
+
+  __ pop(ebx);
+  __ push(receiver);
+  __ push(name);
+  __ push(ebx);
+}
+
+
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index 6d54b07..4f8ee08 100644 (file)
@@ -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,7 +268,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;
@@ -285,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);
@@ -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);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
@@ -623,7 +630,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -658,7 +665,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // Return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -670,7 +677,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ push(ebx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -688,7 +698,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // Return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -700,7 +710,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ push(ebx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
index dee91ff..0794342 100644 (file)
@@ -88,7 +88,7 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
 
 
 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();
@@ -97,8 +97,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();
@@ -113,7 +113,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;
 }
@@ -221,7 +222,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);
@@ -232,7 +233,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(),
index 47dfe08..b5226e9 100644 (file)
@@ -32,12 +32,13 @@ class PropertyICCompiler : public PropertyAccessCompiler {
 
   // Keyed
   static Handle<Code> ComputeKeyedLoadMonomorphicHandler(
-      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);
index 55572f7..657f0b6 100644 (file)
@@ -135,6 +135,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);
 }
index dbc504b..89e455d 100644 (file)
@@ -201,11 +201,21 @@ class CompareICState {
 
 
 class LoadICState final BASE_EMBEDDED {
+ private:
+  class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
+  class LanguageModeBits : public BitField<LanguageMode, 1, 2> {};
+  STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
+  const ExtraICState state_;
+
  public:
+  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_; }
 
@@ -213,15 +223,17 @@ 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);
-
-  const ExtraICState state_;
+  static LanguageMode GetLanguageMode(ExtraICState state) {
+    return LoadICState(state).language_mode();
+  }
 };
 
 
index 7c14b56..5499d80 100644 (file)
@@ -571,11 +571,14 @@ void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
 
 
 // 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();
   }
 }
 
@@ -679,7 +682,8 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
     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;
   }
 
@@ -722,8 +726,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)) {
@@ -915,25 +920,20 @@ Handle<Code> LoadIC::initialize_stub_in_optimized_code(
 }
 
 
-Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) {
-  return KeyedLoadICTrampolineStub(isolate).GetCode();
+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) {
+    Isolate* isolate, State initialization_state, ExtraICState extra_state) {
   if (initialization_state != MEGAMORPHIC) {
-    return KeyedLoadICStub(isolate).GetCode();
+    return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode();
   }
-  switch (initialization_state) {
-    case UNINITIALIZED:
-      return isolate->builtins()->KeyedLoadIC_Initialize();
-    case MEGAMORPHIC:
-      return isolate->builtins()->KeyedLoadIC_Megamorphic();
-    default:
-      UNREACHABLE();
-  }
-  return Handle<Code>();
+  return is_strong(LoadICState::GetLanguageMode(extra_state))
+             ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong()
+             : isolate->builtins()->KeyedLoadIC_Megamorphic();
 }
 
 
@@ -962,7 +962,7 @@ Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate,
 
 Handle<Code> LoadIC::megamorphic_stub() {
   DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
-  return KeyedLoadIC::ChooseMegamorphicStub(isolate());
+  return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state());
 }
 
 
@@ -986,7 +986,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.
@@ -1245,7 +1245,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
 
   if (target_receiver_maps.length() == 0) {
     Handle<Code> handler =
-        PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
+        PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
+            receiver_map, extra_ic_state());
     ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
     return null_handle;
   }
@@ -1262,7 +1263,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
           target_receiver_maps.at(0)->elements_kind(),
           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
     Handle<Code> handler =
-        PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
+        PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
+            receiver_map, extra_ic_state());
     ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
     return null_handle;
   }
@@ -1287,7 +1289,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
 
   CodeHandleList handlers(target_receiver_maps.length());
   ElementHandlerCompiler compiler(isolate());
-  compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
+  compiler.CompileElementHandlers(&target_receiver_maps, &handlers,
+                                  language_mode());
   ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
   return null_handle;
 }
@@ -1298,7 +1301,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;
   }
@@ -1346,10 +1350,12 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
   }
 
   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;
 }
 
@@ -2812,6 +2818,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));
 
@@ -2857,8 +2864,11 @@ RUNTIME_FUNCTION(LoadElementWithInterceptor) {
   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, Object::GetElement(isolate, receiver, index));
+      isolate, result,
+      Object::GetElement(isolate, receiver, index, language_mode));
   return *result;
 }
 
@@ -2894,6 +2904,36 @@ RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) {
 }
 
 
+RUNTIME_FUNCTION(LoadIC_Slow) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+
+  Handle<Object> receiver = args.at<Object>(0);
+  Handle<Name> name = args.at<Name>(1);
+  LoadIC ic(IC::NO_EXTRA_FRAME, isolate, true);
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      Runtime::GetObjectProperty(isolate, receiver, name, ic.language_mode()));
+  return *result;
+}
+
+
+RUNTIME_FUNCTION(KeyedLoadIC_Slow) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+
+  Handle<Object> receiver = args.at<Object>(0);
+  Handle<Object> key = args.at<Object>(1);
+  LoadIC ic(IC::NO_EXTRA_FRAME, isolate, true);
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver, key,
+                                                       ic.language_mode()));
+  return *result;
+}
+
+
 static const Address IC_utilities[] = {
 #define ADDR(name) FUNCTION_ADDR(name),
     IC_UTIL_LIST(ADDR) NULL
@@ -2902,5 +2942,5 @@ static const Address IC_utilities[] = {
 
 
 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; }
-}  // namespace internal
-}  // namespace v8
+}
+}  // namespace v8::internal
index c346306..935d856 100644 (file)
@@ -18,6 +18,8 @@ namespace internal {
 #define IC_UTIL_LIST(ICU)              \
   ICU(LoadIC_Miss)                     \
   ICU(KeyedLoadIC_Miss)                \
+  ICU(LoadIC_Slow)                     \
+  ICU(KeyedLoadIC_Slow)                \
   ICU(CallIC_Miss)                     \
   ICU(CallIC_Customization_Miss)       \
   ICU(StoreIC_Miss)                    \
@@ -352,14 +354,19 @@ 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(nexus != NULL);
@@ -390,7 +397,7 @@ class LoadIC : public IC {
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateNormal(MacroAssembler* masm);
-  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
+  static void GenerateSlow(MacroAssembler* masm);
 
   static Handle<Code> initialize_stub(Isolate* isolate,
                                       ExtraICState extra_state);
@@ -437,11 +444,12 @@ 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, 2, 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);
   }
 
@@ -461,9 +469,10 @@ class KeyedLoadIC : public LoadIC {
 
   // Code generator routines.
   static void GenerateMiss(MacroAssembler* masm);
-  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
+  static void GenerateSlow(MacroAssembler* masm);
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
-  static void GenerateMegamorphic(MacroAssembler* masm);
+  static void GenerateMegamorphic(MacroAssembler* masm,
+                                  LanguageMode languageMode);
 
   // Bit mask to be tested against bit field for the cases when
   // generic stub should go into slow case.
@@ -472,10 +481,12 @@ 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);
+      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);
 
index 13ce921..34c11b1 100644 (file)
@@ -16,6 +16,30 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index 7dbaad7..0170959 100644 (file)
@@ -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.
@@ -285,7 +291,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -320,13 +326,16 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in ra.
 
   __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
   __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -349,16 +358,20 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in ra.
 
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 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;
@@ -382,7 +395,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();
 
@@ -403,7 +417,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   __ bind(&slow);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, t0,
                       a3);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);
index d83c807..2a0ec06 100644 (file)
@@ -16,6 +16,30 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index 770fa77..cbe9c0d 100644 (file)
@@ -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.
@@ -283,7 +288,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -318,7 +323,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in ra.
 
   __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
@@ -347,7 +352,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in ra.
 
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
@@ -356,7 +361,8 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
 }
 
 
-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;
@@ -380,7 +386,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();
 
@@ -401,7 +408,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   __ bind(&slow);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, a4,
                       a3);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);
index 8988b08..0a802f0 100644 (file)
@@ -16,6 +16,30 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::LoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void NamedLoadHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Push receiver and key for runtime call.
+  __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::KeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index fdb88ae..6b4fc45 100644 (file)
@@ -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.
@@ -288,7 +294,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -323,13 +329,16 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
 
   __ mr(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
   __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -351,16 +360,20 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is in lr.
 
   __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
 
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 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;
@@ -384,7 +397,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();
 
@@ -406,7 +420,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   __ bind(&slow);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r7,
                       r6);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, r3, r6, &index_name, &slow);
index 43754c3..73fecca 100644 (file)
@@ -261,6 +261,39 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
 }
 
 
+static void LoadIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = LoadDescriptor::ReceiverRegister();
+  Register name = LoadDescriptor::NameRegister();
+
+  DCHECK(!rbx.is(receiver) && !rbx.is(name));
+
+  __ PopReturnAddressTo(rbx);
+  __ Push(receiver);
+  __ Push(name);
+  __ PushReturnAddressFrom(rbx);
+}
+
+
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index 40aa231..6d40a50 100644 (file)
@@ -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);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
@@ -623,7 +630,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -660,7 +667,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -672,7 +679,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ PushReturnAddressFrom(rbx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -691,7 +701,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // The return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -703,7 +713,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ PushReturnAddressFrom(rbx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
index 056bd95..256c863 100644 (file)
@@ -16,6 +16,39 @@ namespace internal {
 #define __ ACCESS_MASM(masm)
 
 
+static void LoadIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = LoadDescriptor::ReceiverRegister();
+  Register name = LoadDescriptor::NameRegister();
+
+  DCHECK(!ebx.is(receiver) && !ebx.is(name));
+
+  __ pop(ebx);
+  __ push(receiver);
+  __ push(name);
+  __ push(ebx);
+}
+
+
+void NamedLoadHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void ElementHandlerCompiler::GenerateLoadSlow(MacroAssembler* masm) {
+  // Return address is on the stack.
+  LoadIC_PushArgs(masm);
+
+  // Do tail-call to runtime routine.
+  ExternalReference ref(IC_Utility(IC::kKeyedLoadIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
     MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
     int accessor_index, int expected_arguments, Register scratch) {
index ee236a6..daa2ac0 100644 (file)
@@ -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,7 +268,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;
@@ -285,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);
@@ -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);
+  GenerateSlow(masm);
 
   __ bind(&check_name);
   GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
@@ -623,7 +630,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
 
   // Dictionary load failed, go slow (but don't miss).
   __ bind(&slow);
-  GenerateRuntimeGetProperty(masm);
+  GenerateSlow(masm);
 }
 
 
@@ -658,7 +665,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateSlow(MacroAssembler* masm) {
   // Return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -670,7 +677,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ push(ebx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
@@ -688,7 +698,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
   // Return address is on the stack.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
@@ -700,7 +710,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   __ push(ebx);
 
   // Perform tail call to the entry.
-  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
+  int arg_count = 2;
+  __ TailCallExternalReference(ref, arg_count, 1);
 }
 
 
index 1862ff1..98eaf48 100644 (file)
@@ -373,6 +373,8 @@ class CallSite {
     "instead")                                                                 \
   T(StrongForIn,                                                               \
     "In strong mode, 'for'-'in' loops are deprecated, use 'for'-'of' instead") \
+  T(StrongPropertyAccess,                                                      \
+    "In strong mode, accessing missing property '%' of % is deprecated")       \
   T(StrongSuperCallDuplicate,                                                  \
     "In strong mode, invoking the super constructor multiple times is "        \
     "deprecated")                                                              \
index 1b84534..aefc448 100644 (file)
@@ -4592,7 +4592,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4805,7 +4805,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&try_poly_name, ne, at, Operand(feedback));
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index a44e02d..79d38b8 100644 (file)
@@ -2229,7 +2229,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ lw(load_name, MemOperand(sp, 2 * kPointerSize));
       __ li(LoadDescriptor::SlotRegister(),
             Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(a0, v0);
       __ mov(a1, a0);
@@ -2400,7 +2400,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ li(LoadDescriptor::NameRegister(), Operand(key->value()));
   __ li(LoadDescriptor::SlotRegister(),
         Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2412,13 +2412,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ li(LoadDescriptor::SlotRegister(),
         Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2427,9 +2428,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2975,6 +2977,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2982,7 +2985,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ sw(v0, MemOperand(sp, kPointerSize));
@@ -3033,6 +3037,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -3040,7 +3045,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ sw(v0, MemOperand(sp, kPointerSize));
index ccf0e53..2180215 100644 (file)
@@ -2866,7 +2866,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -2966,9 +2966,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   // Name is always in a2.
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3293,9 +3294,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 8c539b4..3baf78e 100644 (file)
@@ -4636,7 +4636,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4847,7 +4847,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&try_poly_name, ne, feedback, Operand(at));
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index 39abc3f..6c06cf7 100644 (file)
@@ -2226,7 +2226,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ ld(load_name, MemOperand(sp, 2 * kPointerSize));
       __ li(LoadDescriptor::SlotRegister(),
             Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(a0, v0);
       __ mov(a1, a0);
@@ -2399,7 +2399,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ li(LoadDescriptor::NameRegister(), Operand(key->value()));
   __ li(LoadDescriptor::SlotRegister(),
         Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2411,14 +2411,15 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
   // Call keyed load IC. It has register arguments receiver and key.
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ li(LoadDescriptor::SlotRegister(),
         Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2427,9 +2428,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2978,6 +2980,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2985,7 +2988,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ sd(v0, MemOperand(sp, kPointerSize));
@@ -3036,6 +3040,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -3043,7 +3048,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ sd(v0, MemOperand(sp, kPointerSize));
index 0082a3f..8b5dca3 100644 (file)
@@ -2970,7 +2970,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -3085,9 +3085,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   // Name is always in a2.
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3454,9 +3455,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 86a3fe7..7a31d1a 100644 (file)
@@ -1162,17 +1162,18 @@ bool Object::HasSpecificClassOf(String* name) {
 
 
 MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
-                                        Handle<Name> name) {
+                                        Handle<Name> name,
+                                        LanguageMode language_mode) {
   LookupIterator it(object, name);
-  return GetProperty(&it);
+  return GetProperty(&it, language_mode);
 }
 
 
-MaybeHandle<Object> Object::GetElement(Isolate* isolate,
-                                       Handle<Object> object,
-                                       uint32_t index) {
+MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
+                                       uint32_t index,
+                                       LanguageMode language_mode) {
   LookupIterator it(isolate, object, index);
-  return GetProperty(&it);
+  return GetProperty(&it, language_mode);
 }
 
 
@@ -1189,11 +1190,11 @@ Handle<Object> Object::GetPrototypeSkipHiddenPrototypes(
 }
 
 
-MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
-                                        Handle<Object> object,
-                                        const char* name) {
+MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
+                                        const char* name,
+                                        LanguageMode language_mode) {
   Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
-  return GetProperty(object, str);
+  return GetProperty(object, str, language_mode);
 }
 
 
@@ -6557,10 +6558,11 @@ String* String::GetForwardedInternalizedString() {
 
 
 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
-                                                 Handle<Name> name) {
+                                                 Handle<Name> name,
+                                                 LanguageMode language_mode) {
   LookupIterator it =
       LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
-  return GetProperty(&it);
+  return GetProperty(&it, language_mode);
 }
 
 
index 0b22420..ec893c9 100644 (file)
@@ -127,7 +127,8 @@ bool Object::IsPromise(Handle<Object> object) {
 }
 
 
-MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
+MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
+                                        LanguageMode language_mode) {
   for (; it->IsFound(); it->Next()) {
     switch (it->state()) {
       case LookupIterator::NOT_FOUND:
@@ -147,16 +148,16 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
       }
       case LookupIterator::ACCESS_CHECK:
         if (it->HasAccess()) break;
-        return JSObject::GetPropertyWithFailedAccessCheck(it);
+        return JSObject::GetPropertyWithFailedAccessCheck(it, language_mode);
       case LookupIterator::ACCESSOR:
-        return GetPropertyWithAccessor(it);
+        return GetPropertyWithAccessor(it, language_mode);
       case LookupIterator::INTEGER_INDEXED_EXOTIC:
-        return it->factory()->undefined_value();
+        return ReadAbsentProperty(it, language_mode);
       case LookupIterator::DATA:
         return it->GetDataValue();
     }
   }
-  return it->factory()->undefined_value();
+  return ReadAbsentProperty(it, language_mode);
 }
 
 
@@ -304,7 +305,8 @@ MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
 }
 
 
-MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
+MaybeHandle<Object> Object::GetPropertyWithAccessor(
+    LookupIterator* it, LanguageMode language_mode) {
   Isolate* isolate = it->isolate();
   Handle<Object> structure = it->GetAccessors();
   Handle<Object> receiver = it->GetReceiver();
@@ -336,7 +338,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
         args.Call(call_fun, v8::Utils::ToLocal(name));
     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
     if (result.IsEmpty()) {
-      return isolate->factory()->undefined_value();
+      return ReadAbsentProperty(isolate, receiver, name, language_mode);
     }
     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
     return_value->VerifyApiCallResultType();
@@ -352,7 +354,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
         receiver, Handle<JSReceiver>::cast(getter));
   }
   // Getter is not a function.
-  return isolate->factory()->undefined_value();
+  return ReadAbsentProperty(isolate, receiver, it->GetName(), language_mode);
 }
 
 
@@ -488,11 +490,11 @@ static bool FindAllCanReadHolder(LookupIterator* it) {
 
 
 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
-    LookupIterator* it) {
+    LookupIterator* it, LanguageMode language_mode) {
   Handle<JSObject> checked = it->GetHolder<JSObject>();
   while (FindAllCanReadHolder(it)) {
     if (it->state() == LookupIterator::ACCESSOR) {
-      return GetPropertyWithAccessor(it);
+      return GetPropertyWithAccessor(it, language_mode);
     }
     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
     bool done;
@@ -3223,6 +3225,26 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
 }
 
 
+MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it,
+                                               LanguageMode language_mode) {
+  return ReadAbsentProperty(it->isolate(), it->GetReceiver(), it->GetName(),
+                            language_mode);
+}
+
+MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
+                                               Handle<Object> receiver,
+                                               Handle<Object> name,
+                                               LanguageMode language_mode) {
+  if (is_strong(language_mode)) {
+    THROW_NEW_ERROR(
+        isolate,
+        NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver),
+        Object);
+  }
+  return isolate->factory()->undefined_value();
+}
+
+
 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
index ccf3506..9fa0e72 100644 (file)
@@ -1155,7 +1155,8 @@ class Object {
   MUST_USE_RESULT static inline MaybeHandle<Smi> ToSmi(Isolate* isolate,
                                                        Handle<Object> object);
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it);
+  MUST_USE_RESULT static MaybeHandle<Object> GetProperty(
+      LookupIterator* it, LanguageMode language_mode = SLOPPY);
 
   // Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5.
   MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
@@ -1171,10 +1172,15 @@ class Object {
       LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
       StoreFromKeyed store_mode);
 
+  MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty(
+      LookupIterator* it, LanguageMode language_mode);
+  MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty(
+      Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
+      LanguageMode language_mode);
   MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
       LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
   MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
-      Isolate* isolate, Handle<Object> reciever, Handle<Object> name,
+      Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
       Handle<Object> value, LanguageMode language_mode);
   MUST_USE_RESULT static MaybeHandle<Object> RedefineNonconfigurableProperty(
       Isolate* isolate, Handle<Object> name, Handle<Object> value,
@@ -1185,16 +1191,17 @@ class Object {
       LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
       LanguageMode language_mode, StoreFromKeyed store_mode);
   MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
-      Handle<Object> object, Handle<Name> name);
+      Handle<Object> object, Handle<Name> name,
+      LanguageMode language_mode = SLOPPY);
   MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
-      Isolate* isolate,
-      Handle<Object> object,
-      const char* key);
+      Isolate* isolate, Handle<Object> object, const char* key,
+      LanguageMode language_mode = SLOPPY);
   MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
-      Handle<Object> object, Handle<Name> name);
+      Handle<Object> object, Handle<Name> name,
+      LanguageMode language_mode = SLOPPY);
 
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
-      LookupIterator* it);
+      LookupIterator* it, LanguageMode language_mode);
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
       LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
 
@@ -1207,9 +1214,8 @@ class Object {
       Handle<Object> value);
 
   MUST_USE_RESULT static inline MaybeHandle<Object> GetElement(
-      Isolate* isolate,
-      Handle<Object> object,
-      uint32_t index);
+      Isolate* isolate, Handle<Object> object, uint32_t index,
+      LanguageMode language_mode = SLOPPY);
 
   static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
       Isolate* isolate, Handle<Object> receiver);
@@ -2328,7 +2334,7 @@ class JSObject: public JSReceiver {
 
   // Used from Object::GetProperty().
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
-      LookupIterator* it);
+      LookupIterator* it, LanguageMode language_mode);
 
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
       LookupIterator* it, Handle<Object> value);
index 9cc2bed..66124fb 100644 (file)
@@ -4612,7 +4612,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4829,7 +4829,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ bne(&try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index 2e34d16..bac4496 100644 (file)
@@ -2200,7 +2200,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ LoadP(load_name, MemOperand(sp, 2 * kPointerSize));
       __ mov(LoadDescriptor::SlotRegister(),
              Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mr(r4, r3);
       __ StoreP(r4, MemOperand(sp, 2 * kPointerSize));
@@ -2389,7 +2389,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ mov(LoadDescriptor::NameRegister(), Operand(key->value()));
   __ mov(LoadDescriptor::SlotRegister(),
          Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2401,13 +2401,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ mov(LoadDescriptor::SlotRegister(),
          Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2416,9 +2417,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2990,6 +2992,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, r3, r3, scratch);
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2997,7 +3000,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ StoreP(r3, MemOperand(sp, kPointerSize));
@@ -3047,6 +3051,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, r3, r3, scratch);
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -3054,7 +3059,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ StoreP(r3, MemOperand(sp, kPointerSize));
index fea04e3..cc2bb5a 100644 (file)
@@ -3025,7 +3025,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -3141,9 +3141,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   // Name is always in r5.
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3515,9 +3516,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index dedff92..95a65f5 100644 (file)
@@ -120,7 +120,8 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
           isolate, prototype_parent,
           Runtime::GetObjectProperty(isolate, super_class,
-                                     isolate->factory()->prototype_string()));
+                                     isolate->factory()->prototype_string(),
+                                     SLOPPY));
       if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
         THROW_NEW_ERROR_RETURN_FAILURE(
             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
@@ -244,64 +245,87 @@ RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
 }
 
 
-static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
-                             Handle<JSObject> home_object, Handle<Name> name) {
+static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
+                                         Handle<Object> receiver,
+                                         Handle<JSObject> home_object,
+                                         Handle<Name> name,
+                                         LanguageMode language_mode) {
   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
     isolate->ReportFailedAccessCheck(home_object);
-    RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   }
 
   PrototypeIterator iter(isolate, home_object);
   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
-  if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
+  if (!proto->IsJSReceiver()) {
+    return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
+  }
 
   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
   Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
-  return *result;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
+                             Object::GetProperty(&it, language_mode), Object);
+  return result;
 }
 
 
-static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
-                                    Handle<JSObject> home_object,
-                                    uint32_t index) {
+static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
+                                                Handle<Object> receiver,
+                                                Handle<JSObject> home_object,
+                                                uint32_t index,
+                                                LanguageMode language_mode) {
   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
     isolate->ReportFailedAccessCheck(home_object);
-    RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   }
 
   PrototypeIterator iter(isolate, home_object);
   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
-  if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
+  if (!proto->IsJSReceiver()) {
+    Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
+    return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
+  }
 
   LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
   Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
-  return *result;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
+                             Object::GetProperty(&it, language_mode), Object);
+  return result;
 }
 
 
 RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
+  DCHECK(args.length() == 4);
   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
+  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
 
-  return LoadFromSuper(isolate, receiver, home_object, name);
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      LoadFromSuper(isolate, receiver, home_object, name, language_mode));
+  return *result;
 }
 
 
 RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
+  DCHECK(args.length() == 4);
   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
+  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
 
   uint32_t index = 0;
+  Handle<Object> result;
+
   if (key->ToArrayIndex(&index)) {
-    return LoadElementFromSuper(isolate, receiver, home_object, index);
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
+                                              index, language_mode));
+    return *result;
   }
 
   Handle<Name> name;
@@ -309,9 +333,15 @@ RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
                                      Runtime::ToName(isolate, key));
   // TODO(verwaest): Unify using LookupIterator.
   if (name->AsArrayIndex(&index)) {
-    return LoadElementFromSuper(isolate, receiver, home_object, index);
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
+                                              index, language_mode));
+    return *result;
   }
-  return LoadFromSuper(isolate, receiver, home_object, name);
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      LoadFromSuper(isolate, receiver, home_object, name, language_mode));
+  return *result;
 }
 
 
index 5baa151..1c808a7 100644 (file)
@@ -81,7 +81,7 @@ static Handle<Object> DebugGetProperty(LookupIterator* it,
           return it->isolate()->factory()->undefined_value();
         }
         MaybeHandle<Object> maybe_result =
-            JSObject::GetPropertyWithAccessor(it);
+            JSObject::GetPropertyWithAccessor(it, SLOPPY);
         Handle<Object> result;
         if (!maybe_result.ToHandle(&result)) {
           result = handle(it->isolate()->pending_exception(), it->isolate());
index b3b917b..d119867 100644 (file)
@@ -26,7 +26,8 @@ static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
 
 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
                                                 Handle<Object> object,
-                                                uint32_t index) {
+                                                uint32_t index,
+                                                LanguageMode language_mode) {
   // Handle [] indexing on Strings
   if (object->IsString() &&
       index < static_cast<uint32_t>(String::cast(*object)->length())) {
@@ -34,7 +35,7 @@ MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
     if (!result->IsUndefined()) return result;
   }
 
-  return Object::GetElement(isolate, object, index);
+  return Object::GetElement(isolate, object, index, language_mode);
 }
 
 
@@ -52,7 +53,8 @@ MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
 
 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
                                                Handle<Object> object,
-                                               Handle<Object> key) {
+                                               Handle<Object> key,
+                                               LanguageMode language_mode) {
   if (object->IsUndefined() || object->IsNull()) {
     THROW_NEW_ERROR(
         isolate,
@@ -63,7 +65,7 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
   // Check if the given key is an array index.
   uint32_t index = 0;
   if (key->ToArrayIndex(&index)) {
-    return GetElementOrCharAt(isolate, object, index);
+    return GetElementOrCharAt(isolate, object, index, language_mode);
   }
 
   // Convert the key to a name - possibly by calling back into JavaScript.
@@ -77,8 +79,109 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
   if (name->AsArrayIndex(&index)) {
     return GetElementOrCharAt(isolate, object, index);
   } else {
-    return Object::GetProperty(object, name);
+    return Object::GetProperty(object, name, language_mode);
+  }
+}
+
+
+MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
+    Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
+  HandleScope scope(isolate);
+  if (!object->IsJSObject()) {
+    isolate->ThrowIllegalOperation();
+    return MaybeHandle<Object>();
+  }
+  ElementsKind from_kind =
+      Handle<JSObject>::cast(object)->map()->elements_kind();
+  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
+    JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
+    return object;
   }
+  isolate->ThrowIllegalOperation();
+  return MaybeHandle<Object>();
+}
+
+
+MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
+    Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
+    LanguageMode language_mode) {
+  // Fast cases for getting named properties of the receiver JSObject
+  // itself.
+  //
+  // The global proxy objects has to be excluded since LookupOwn on
+  // the global proxy object can return a valid result even though the
+  // global proxy object never has properties.  This is the case
+  // because the global proxy object forwards everything to its hidden
+  // prototype including own lookups.
+  //
+  // Additionally, we need to make sure that we do not cache results
+  // for objects that require access checks.
+  if (receiver_obj->IsJSObject()) {
+    if (!receiver_obj->IsJSGlobalProxy() &&
+        !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
+      DisallowHeapAllocation no_allocation;
+      Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
+      Handle<Name> key = Handle<Name>::cast(key_obj);
+      if (receiver->IsGlobalObject()) {
+        // Attempt dictionary lookup.
+        GlobalDictionary* dictionary = receiver->global_dictionary();
+        int entry = dictionary->FindEntry(key);
+        if (entry != GlobalDictionary::kNotFound) {
+          DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
+          PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
+          if (cell->property_details().type() == DATA) {
+            Object* value = cell->value();
+            if (!value->IsTheHole()) return Handle<Object>(value, isolate);
+            // If value is the hole (meaning, absent) do the general lookup.
+          }
+        }
+      } else if (!receiver->HasFastProperties()) {
+        // Attempt dictionary lookup.
+        NameDictionary* dictionary = receiver->property_dictionary();
+        int entry = dictionary->FindEntry(key);
+        if ((entry != NameDictionary::kNotFound) &&
+            (dictionary->DetailsAt(entry).type() == DATA)) {
+          Object* value = dictionary->ValueAt(entry);
+          return Handle<Object>(value, isolate);
+        }
+      }
+    } else if (key_obj->IsSmi()) {
+      // JSObject without a name key. If the key is a Smi, check for a
+      // definite out-of-bounds access to elements, which is a strong indicator
+      // that subsequent accesses will also call the runtime. Proactively
+      // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
+      // doubles for those future calls in the case that the elements would
+      // become FAST_DOUBLE_ELEMENTS.
+      Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
+      ElementsKind elements_kind = js_object->GetElementsKind();
+      if (IsFastDoubleElementsKind(elements_kind)) {
+        Handle<Smi> key = Handle<Smi>::cast(key_obj);
+        if (key->value() >= js_object->elements()->length()) {
+          if (IsFastHoleyElementsKind(elements_kind)) {
+            elements_kind = FAST_HOLEY_ELEMENTS;
+          } else {
+            elements_kind = FAST_ELEMENTS;
+          }
+          RETURN_ON_EXCEPTION(
+              isolate, TransitionElements(js_object, elements_kind, isolate),
+              Object);
+        }
+      } else {
+        DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
+               !IsFastElementsKind(elements_kind));
+      }
+    }
+  } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
+    // Fast case for string indexing using [] with a smi index.
+    Handle<String> str = Handle<String>::cast(receiver_obj);
+    int index = Handle<Smi>::cast(key_obj)->value();
+    if (index >= 0 && index < str->length()) {
+      return GetCharAt(str, index);
+    }
+  }
+
+  // Fall back to GetObjectProperty.
+  return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
 }
 
 
@@ -383,122 +486,32 @@ RUNTIME_FUNCTION(Runtime_ObjectSeal) {
 
 RUNTIME_FUNCTION(Runtime_GetProperty) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
+  DCHECK(args.length() == 3);
 
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
+
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Runtime::GetObjectProperty(isolate, object, key));
+      isolate, result,
+      Runtime::GetObjectProperty(isolate, object, key, language_mode));
   return *result;
 }
 
 
-MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
-    Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
-  HandleScope scope(isolate);
-  if (!object->IsJSObject()) {
-    isolate->ThrowIllegalOperation();
-    return MaybeHandle<Object>();
-  }
-  ElementsKind from_kind =
-      Handle<JSObject>::cast(object)->map()->elements_kind();
-  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
-    JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
-    return object;
-  }
-  isolate->ThrowIllegalOperation();
-  return MaybeHandle<Object>();
-}
-
-
-// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
+  DCHECK(args.length() == 3);
 
   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
+  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
 
-  // Fast cases for getting named properties of the receiver JSObject
-  // itself.
-  //
-  // The global proxy objects has to be excluded since LookupOwn on
-  // the global proxy object can return a valid result even though the
-  // global proxy object never has properties.  This is the case
-  // because the global proxy object forwards everything to its hidden
-  // prototype including own lookups.
-  //
-  // Additionally, we need to make sure that we do not cache results
-  // for objects that require access checks.
-  if (receiver_obj->IsJSObject()) {
-    if (!receiver_obj->IsJSGlobalProxy() &&
-        !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
-      DisallowHeapAllocation no_allocation;
-      Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
-      Handle<Name> key = Handle<Name>::cast(key_obj);
-      if (receiver->IsGlobalObject()) {
-        // Attempt dictionary lookup.
-        GlobalDictionary* dictionary = receiver->global_dictionary();
-        int entry = dictionary->FindEntry(key);
-        if (entry != GlobalDictionary::kNotFound) {
-          DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
-          PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
-          if (cell->property_details().type() == DATA) {
-            Object* value = cell->value();
-            if (!value->IsTheHole()) return value;
-            // If value is the hole (meaning, absent) do the general lookup.
-          }
-        }
-      } else if (!receiver->HasFastProperties()) {
-        // Attempt dictionary lookup.
-        NameDictionary* dictionary = receiver->property_dictionary();
-        int entry = dictionary->FindEntry(key);
-        if ((entry != NameDictionary::kNotFound) &&
-            (dictionary->DetailsAt(entry).type() == DATA)) {
-          Object* value = dictionary->ValueAt(entry);
-          return value;
-        }
-      }
-    } else if (key_obj->IsSmi()) {
-      // JSObject without a name key. If the key is a Smi, check for a
-      // definite out-of-bounds access to elements, which is a strong indicator
-      // that subsequent accesses will also call the runtime. Proactively
-      // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
-      // doubles for those future calls in the case that the elements would
-      // become FAST_DOUBLE_ELEMENTS.
-      Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
-      ElementsKind elements_kind = js_object->GetElementsKind();
-      if (IsFastDoubleElementsKind(elements_kind)) {
-        Handle<Smi> key = Handle<Smi>::cast(key_obj);
-        if (key->value() >= js_object->elements()->length()) {
-          if (IsFastHoleyElementsKind(elements_kind)) {
-            elements_kind = FAST_HOLEY_ELEMENTS;
-          } else {
-            elements_kind = FAST_ELEMENTS;
-          }
-          RETURN_FAILURE_ON_EXCEPTION(
-              isolate, TransitionElements(js_object, elements_kind, isolate));
-        }
-      } else {
-        DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
-               !IsFastElementsKind(elements_kind));
-      }
-    }
-  } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
-    // Fast case for string indexing using [] with a smi index.
-    Handle<String> str = Handle<String>::cast(receiver_obj);
-    int index = args.smi_at(1);
-    if (index >= 0 && index < str->length()) {
-      return *GetCharAt(str, index);
-    }
-  }
-
-  // Fall back to GetObjectProperty.
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
+      isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver_obj,
+                                                       key_obj, language_mode));
   return *result;
 }
 
index b8918c4..cf0b882 100644 (file)
@@ -78,8 +78,8 @@ namespace internal {
   F(DefineClass, 6, 1)                        \
   F(DefineClassMethod, 3, 1)                  \
   F(ClassGetSourceCode, 1, 1)                 \
-  F(LoadFromSuper, 3, 1)                      \
-  F(LoadKeyedFromSuper, 3, 1)                 \
+  F(LoadFromSuper, 4, 1)                      \
+  F(LoadKeyedFromSuper, 4, 1)                 \
   F(StoreToSuper_Strict, 4, 1)                \
   F(StoreToSuper_Sloppy, 4, 1)                \
   F(StoreKeyedToSuper_Strict, 4, 1)           \
@@ -431,8 +431,8 @@ namespace internal {
   F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
   F(ObjectFreeze, 1, 1)                              \
   F(ObjectSeal, 1, 1)                                \
-  F(GetProperty, 2, 1)                               \
-  F(KeyedGetProperty, 2, 1)                          \
+  F(GetProperty, 3, 1)                               \
+  F(KeyedGetProperty, 3, 1)                          \
   F(AddNamedProperty, 4, 1)                          \
   F(SetProperty, 4, 1)                               \
   F(AddElement, 3, 1)                                \
@@ -815,14 +815,20 @@ class Runtime : public AllStatic {
   // Support getting the characters in a string using [] notation as
   // in Firefox/SpiderMonkey, Safari and Opera.
   MUST_USE_RESULT static MaybeHandle<Object> GetElementOrCharAt(
-      Isolate* isolate, Handle<Object> object, uint32_t index);
+      Isolate* isolate, Handle<Object> object, uint32_t index,
+      LanguageMode language_mode = SLOPPY);
 
   MUST_USE_RESULT static MaybeHandle<Object> SetObjectProperty(
       Isolate* isolate, Handle<Object> object, Handle<Object> key,
       Handle<Object> value, LanguageMode language_mode);
 
   MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
-      Isolate* isolate, Handle<Object> object, Handle<Object> key);
+      Isolate* isolate, Handle<Object> object, Handle<Object> key,
+      LanguageMode language_mode = SLOPPY);
+
+  MUST_USE_RESULT static MaybeHandle<Object> KeyedGetObjectProperty(
+      Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
+      LanguageMode language_mode);
 
   MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
       Isolate* isolate, Handle<Object> object);
index 48a2a88..3b896c5 100644 (file)
@@ -4375,7 +4375,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4554,7 +4554,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ j(not_equal, &try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index 7560117..abe53ff 100644 (file)
@@ -2196,7 +2196,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ movp(load_receiver, Operand(rsp, kPointerSize));
       __ Move(LoadDescriptor::SlotRegister(),
               SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ movp(rdi, rax);
       __ movp(Operand(rsp, 2 * kPointerSize), rdi);
@@ -2364,7 +2364,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ Move(LoadDescriptor::NameRegister(), key->value());
   __ Move(LoadDescriptor::SlotRegister(),
           SmiFromSlot(prop->PropertyFeedbackSlot()));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2376,13 +2376,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ Push(key->value());
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ Push(Smi::FromInt(language_mode()));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ Move(LoadDescriptor::SlotRegister(),
           SmiFromSlot(prop->PropertyFeedbackSlot()));
   CallIC(ic);
@@ -2391,9 +2392,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ Push(Smi::FromInt(language_mode()));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2889,6 +2891,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   __ Push(rax);
   __ Push(Operand(rsp, kPointerSize * 2));
   __ Push(key->value());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2896,7 +2899,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ movp(Operand(rsp, kPointerSize), rax);
@@ -2946,6 +2950,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   __ Push(rax);
   __ Push(Operand(rsp, kPointerSize * 2));
   VisitForStackValue(prop->key());
+  __ Push(Smi::FromInt(language_mode()));
 
   // Stack here:
   //  - home_object
@@ -2953,7 +2958,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ movp(Operand(rsp, kPointerSize), rax);
index 331584a..20619e6 100644 (file)
@@ -2864,7 +2864,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ Move(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -2980,9 +2980,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
 
   __ Move(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3278,9 +3279,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
+                        isolate(), instr->hydrogen()->language_mode(),
+                        instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index cab0000..ccf5173 100644 (file)
@@ -4090,7 +4090,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate());
+  KeyedLoadICStub stub(isolate(), state());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4294,7 +4294,7 @@ void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ j(not_equal, &try_poly_name);
   Handle<Code> megamorphic_stub =
-      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
+      KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
   __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
 
   __ bind(&try_poly_name);
index 9798a50..3a3d14d 100644 (file)
@@ -2157,7 +2157,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ mov(load_receiver, Operand(esp, kPointerSize));
       __ mov(LoadDescriptor::SlotRegister(),
              Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
-      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+      Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(edi, eax);
       __ mov(Operand(esp, 2 * kPointerSize), edi);
@@ -2326,7 +2326,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   __ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
   __ mov(LoadDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
+  CallLoadIC(NOT_CONTEXTUAL, language_mode());
 }
 
 
@@ -2338,13 +2338,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   DCHECK(prop->IsSuperAccess());
 
   __ push(Immediate(key->value()));
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  __ push(Immediate(Smi::FromInt(language_mode())));
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
   __ mov(LoadDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
   CallIC(ic);
@@ -2353,9 +2354,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   // Stack: receiver, home_object, key.
+  __ push(Immediate(Smi::FromInt(language_mode())));
   SetSourcePosition(prop->position());
 
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 }
 
 
@@ -2885,13 +2887,15 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   __ push(eax);
   __ push(Operand(esp, kPointerSize * 2));
   __ push(Immediate(key->value()));
+  __ push(Immediate(Smi::FromInt(language_mode())));
   // Stack here:
   //  - home_object
   //  - this (receiver)
   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadFromSuper, 4);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2941,13 +2945,15 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   __ push(eax);
   __ push(Operand(esp, kPointerSize * 2));
   VisitForStackValue(prop->key());
+  __ push(Immediate(Smi::FromInt(language_mode())));
   // Stack here:
   //  - home_object
   //  - this (receiver)
   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   //  - home_object
   //  - key
-  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+  //  - language_mode
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
index e59d256..30ffc15 100644 (file)
@@ -3116,7 +3116,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode, SLOPPY,
                                                        PREMONOMORPHIC).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -3226,9 +3226,10 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
 
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_CONTEXTUAL,
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(
+          isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3467,9 +3468,10 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic =
+  Handle<Code> ic = Handle<Code> ic =
       CodeFactory::KeyedLoadICInOptimizedCode(
-          isolate(), instr->hydrogen()->initialization_state()).code();
+          isolate(), instr->hydrogen()->language_mode(),
+          instr->hydrogen()->initialization_state()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 3d8af9f..5c7bac6 100644 (file)
@@ -19356,7 +19356,7 @@ TEST(AccessCheckThrows) {
   CheckCorrectThrow("other[1]");
   CheckCorrectThrow("JSON.stringify(other)");
   CheckCorrectThrow("has_own_property(other, 'x')");
-  CheckCorrectThrow("%GetProperty(other, 'x')");
+  CheckCorrectThrow("%GetProperty(other, 'x', 0)");
   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
index 6956462..a237270 100644 (file)
@@ -47,8 +47,8 @@ function* g() {}
 (function LexicalBindings(global) {
   assertEquals('function', typeof f);
   assertEquals('function', typeof g);
-  assertEquals(undefined, global.f);
-  assertEquals(undefined, global.g);
+  assertFalse(global.hasOwnProperty("f"));
+  assertFalse(global.hasOwnProperty("g"));
 })(this);
 
 (function ImmutableBindings() {
diff --git a/test/mjsunit/strong/load-builtins.js b/test/mjsunit/strong/load-builtins.js
new file mode 100644 (file)
index 0000000..4266cc4
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getGlobal() {
+  return this;
+}
+
+function polluteGlobal() {
+  bar = 0;
+}
+
+(function() {
+  "use strict";
+
+  let builtins = [
+    Array,
+    Object,
+    Function,
+    getGlobal()
+  ];
+
+  for (let builtin of builtins) {
+    assertThrows(function(){"use strong"; builtin.foo}, TypeError);
+    assertThrows(function(){"use strong"; builtin[0]}, TypeError);
+    assertThrows(function(){"use strong"; builtin[10000]}, TypeError);
+    builtin.foo = 1;
+    assertDoesNotThrow(function(){"use strong"; builtin.foo});
+    assertThrows(function(){"use strong"; builtin.bar});
+    assertThrows(function(){"use strong"; builtin[0]}, TypeError);
+    assertThrows(function(){"use strong"; builtin[10000]}, TypeError);
+    builtin[0] = 1;
+    assertDoesNotThrow(function(){"use strong"; builtin.foo});
+    assertThrows(function(){"use strong"; builtin.bar});
+    assertDoesNotThrow(function(){"use strong"; builtin[0]});
+    assertThrows(function(){"use strong"; builtin[10000]}, TypeError);
+  }
+  polluteGlobal();
+  assertDoesNotThrow(function(){"use strong"; getGlobal().bar});
+})();
diff --git a/test/mjsunit/strong/load-element-mutate-backing-store.js b/test/mjsunit/strong/load-element-mutate-backing-store.js
new file mode 100644 (file)
index 0000000..f346502
--- /dev/null
@@ -0,0 +1,239 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getSloppyArguments() {
+  return arguments;
+}
+
+function getObjects() {
+  "use strict";
+  return [
+    {},
+    Object(""),
+    [],
+    (function(){}),
+    (class Foo {}),
+    getSloppyArguments(),
+    arguments,
+    new Date(),
+  ];
+}
+
+// TODO(conradw): add tests for non-inheritance once semantics are implemented.
+function getNonInheritingObjects() {
+  "use strong";
+  return [
+    Object(""),
+    [],
+    // TODO(conradw): uncomment and correct test once Object.defineProperty is
+    // fixed.
+    // new Uint32Array(0)
+  ];
+}
+
+function readFromObjectElementSloppy(o) {
+  return o[0];
+}
+
+function readFromObjectElementSparseSloppy(o) {
+  return o[100000];
+}
+
+function readFromObjectElementNonSmiSloppy(o) {
+  return o[3000000000];
+}
+
+function readFromObjectNonIndexSloppy(o) {
+  return o[5000000000];
+}
+
+function readFromObjectElementVarSloppy(o) {
+  var a = 0;
+  return o[a];
+}
+
+function readFromObjectElementSparseVarSloppy(o) {
+  var a = 100000;
+  return o[a];
+}
+
+function readFromObjectElementNonSmiVarSloppy(o) {
+  var a = 3000000000;
+  return o[a];
+}
+
+function readFromObjectNonIndexVarSloppy(o) {
+  var a = 5000000000;
+  return o[a];
+}
+
+function readFromObjectElementStrong(o) {
+  "use strong";
+  return o[0];
+}
+
+function readFromObjectElementSparseStrong(o) {
+  "use strong";
+  return o[100000];
+}
+
+function readFromObjectElementNonSmiStrong(o) {
+  "use strong";
+  return o[3000000000];
+}
+
+function readFromObjectNonIndexStrong(o) {
+  "use strong";
+  return o[5000000000];
+}
+
+function readFromObjectElementLetStrong(o) {
+  "use strong";
+  let a = 0;
+  return o[a];
+}
+
+function readFromObjectElementSparseLetStrong(o) {
+  "use strong";
+  let a = 100000;
+  return o[a];
+}
+
+function readFromObjectElementNonSmiLetStrong(o) {
+  "use strong";
+  let a = 3000000000;
+  return o[a];
+}
+
+function readFromObjectNonIndexLetStrong(o) {
+  "use strong";
+  let a = 5000000000;
+  return o[a];
+}
+
+function getDescs(x) {
+  return [
+    {value: x},
+    {configurable: true, enumerable: true, writable: true, value: x},
+    {configurable: true, enumerable: true, get: (function() {return x}) },
+  ];
+}
+
+function assertStrongSemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  %OptimizeFunctionOnNextCall(func);
+  assertThrows(function(){func(object)}, TypeError);
+  %DeoptimizeFunction(func);
+  assertThrows(function(){func(object)}, TypeError);
+}
+
+function assertSloppySemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  %OptimizeFunctionOnNextCall(func);
+  assertDoesNotThrow(function(){func(object)});
+  %DeoptimizeFunction(func);
+  assertDoesNotThrow(function(){func(object)});
+}
+
+(function () {
+  "use strict";
+
+  let goodKeys = [
+    "0",
+    "100000",
+    "3000000000",
+    "5000000000"
+  ]
+
+  let badKeys = [
+    "bar",
+    "1",
+    "100001",
+    "3000000001",
+    "5000000001"
+  ];
+
+  let values = [
+    "string",
+    1,
+    100001,
+    30000000001,
+    50000000001,
+    NaN,
+    {},
+    undefined
+  ];
+
+  let badAccessorDescs = [
+    { set: (function(){}) },
+    { configurable: true, enumerable: true, set: (function(){}) }
+  ];
+
+  let readSloppy = [
+    readFromObjectElementSloppy,
+    readFromObjectElementSparseSloppy,
+    readFromObjectElementNonSmiSloppy,
+    readFromObjectNonIndexSloppy,
+    readFromObjectElementVarSloppy,
+    readFromObjectElementSparseVarSloppy,
+    readFromObjectElementNonSmiVarSloppy,
+    readFromObjectNonIndexVarSloppy
+  ];
+
+  let readStrong = [
+    readFromObjectElementStrong,
+    readFromObjectElementSparseStrong,
+    readFromObjectElementNonSmiStrong,
+    readFromObjectNonIndexStrong,
+    readFromObjectElementLetStrong,
+    readFromObjectElementSparseLetStrong,
+    readFromObjectElementNonSmiLetStrong,
+    readFromObjectNonIndexLetStrong
+  ];
+
+  let dummyProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyProto, key, { value: undefined });
+  }
+
+  // After altering the backing store, accessing a missing property should still
+  // throw.
+  for (let key of badKeys) {
+    for (let value of values) {
+      for (let desc of getDescs(value)) {
+        let objects = getObjects();
+        let nonInheritingObjects = getNonInheritingObjects();
+        for (let object of objects.concat(nonInheritingObjects)) {
+          Object.defineProperty(object, key, desc);
+          for (let func of readStrong) {
+            assertStrongSemantics(func, object);
+          }
+          for (let func of readSloppy) {
+            assertSloppySemantics(func, object);
+          }
+        }
+        for (let object of objects) {
+          // Accessing a property which is on the prototype chain of the object
+          // should not throw.
+          object.__proto__ = dummyProto;
+          for (let key of goodKeys) {
+            for (let func of readStrong.concat(readSloppy)) {
+              assertSloppySemantics(func, object);
+            }
+          }
+        }
+      }
+    }
+  }
+})();
diff --git a/test/mjsunit/strong/load-element.js b/test/mjsunit/strong/load-element.js
new file mode 100644 (file)
index 0000000..44c3ed0
--- /dev/null
@@ -0,0 +1,264 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getSloppyArguments() {
+  return arguments;
+}
+
+function getObjects() {
+  "use strict";
+  return [
+    {},
+    Object(""),
+    [],
+    (function(){}),
+    (class Foo {}),
+    getSloppyArguments(),
+    arguments,
+    new Date()
+  ];
+}
+
+//TODO(conradw): add tests for non-inheritance once semantics are implemented.
+function getNonInheritingObjects() {
+  "use strong";
+  return [
+    Object(""),
+    [],
+    new Uint32Array(0)
+  ];
+}
+
+function readFromObjectElementSloppy(o) {
+  return o[0];
+}
+
+function readFromObjectElementSparseSloppy(o) {
+  return o[100000];
+}
+
+function readFromObjectElementNonSmiSloppy(o) {
+  return o[3000000000];
+}
+
+function readFromObjectNonIndexSloppy(o) {
+  return o[5000000000];
+}
+
+function readFromObjectElementVarSloppy(o) {
+  var a = 0;
+  return o[a];
+}
+
+function readFromObjectElementSparseVarSloppy(o) {
+  var a = 100000;
+  return o[a];
+}
+
+function readFromObjectElementNonSmiVarSloppy(o) {
+  var a = 3000000000;
+  return o[a];
+}
+
+function readFromObjectNonIndexVarSloppy(o) {
+  var a = 5000000000;
+  return o[a];
+}
+
+function readFromObjectElementStrong(o) {
+  "use strong";
+  return o[0];
+}
+
+function readFromObjectElementSparseStrong(o) {
+  "use strong";
+  return o[100000];
+}
+
+function readFromObjectElementNonSmiStrong(o) {
+  "use strong";
+  return o[3000000000];
+}
+
+function readFromObjectNonIndexStrong(o) {
+  "use strong";
+  return o[5000000000];
+}
+
+function readFromObjectElementLetStrong(o) {
+  "use strong";
+  let a = 0;
+  return o[a];
+}
+
+function readFromObjectElementSparseLetStrong(o) {
+  "use strong";
+  let a = 100000;
+  return o[a];
+}
+
+function readFromObjectElementNonSmiLetStrong(o) {
+  "use strong";
+  let a = 3000000000;
+  return o[a];
+}
+
+function readFromObjectNonIndexLetStrong(o) {
+  "use strong";
+  let a = 5000000000;
+  return o[a];
+}
+
+function getDescs(x) {
+  return [
+    {value: x},
+    {configurable: true, enumerable: true, writable: true, value: x},
+    {configurable: true, enumerable: true, get: (function() {return x}) },
+  ];
+}
+
+function assertStrongSemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  %OptimizeFunctionOnNextCall(func);
+  assertThrows(function(){func(object)}, TypeError);
+  %DeoptimizeFunction(func);
+  assertThrows(function(){func(object)}, TypeError);
+}
+
+function assertSloppySemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  %OptimizeFunctionOnNextCall(func);
+  assertDoesNotThrow(function(){func(object)});
+  %DeoptimizeFunction(func);
+  assertDoesNotThrow(function(){func(object)});
+}
+
+(function () {
+  "use strict";
+
+  let goodKeys = [
+    "0",
+    "100000",
+    "3000000000",
+    "5000000000"
+  ]
+
+  let badKeys = [
+    "bar",
+    "1",
+    "100001",
+    "3000000001",
+    "5000000001"
+  ];
+
+  let values = [
+    "string",
+    1,
+    100001,
+    30000000001,
+    50000000001,
+    NaN,
+    {},
+    undefined
+  ];
+
+  let literals = [0, NaN, true, ""];
+
+  let badAccessorDescs = [
+    { set: (function(){}) },
+    { configurable: true, enumerable: true, set: (function(){}) }
+  ];
+
+  let readSloppy = [
+    readFromObjectElementSloppy,
+    readFromObjectElementSparseSloppy,
+    readFromObjectElementNonSmiSloppy,
+    readFromObjectNonIndexSloppy,
+    readFromObjectElementVarSloppy,
+    readFromObjectElementSparseVarSloppy,
+    readFromObjectElementNonSmiVarSloppy,
+    readFromObjectNonIndexVarSloppy
+  ];
+
+  let readStrong = [
+    readFromObjectElementStrong,
+    readFromObjectElementSparseStrong,
+    readFromObjectElementNonSmiStrong,
+    readFromObjectNonIndexStrong,
+    readFromObjectElementLetStrong,
+    readFromObjectElementSparseLetStrong,
+    readFromObjectElementNonSmiLetStrong,
+    readFromObjectNonIndexLetStrong
+  ];
+
+  let dummyProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyProto, key, { value: undefined });
+  }
+
+  let dummyAccessorProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) })
+  }
+
+  // String literals/objects should not throw on character index access
+  assertDoesNotThrow(function() {"use strong"; return "string"[0]; });
+  assertDoesNotThrow(function() {"use strong"; return Object("string")[0]; });
+
+  // Attempting to access a property on an object with no defined properties
+  // should throw.
+  for (let object of getObjects().concat(getNonInheritingObjects(), literals)) {
+    for (let func of readStrong) {
+      assertStrongSemantics(func, object);
+    }
+    for (let func of readSloppy) {
+      assertSloppySemantics(func, object);
+    }
+  }
+  for (let object of getObjects()) {
+    // Accessing a property which is on the prototype chain of the object should
+    // not throw.
+    object.__proto__ = dummyProto;
+    for (let key of goodKeys) {
+      for (let func of readStrong.concat(readSloppy)) {
+        assertSloppySemantics(func, object);
+      }
+    }
+  }
+  // Properties with accessor descriptors missing 'get' should throw on access.
+  for (let desc of badAccessorDescs) {
+    for (let key of goodKeys) {
+      for (let object of getObjects()) {
+        Object.defineProperty(object, key, desc);
+        for (let func of readStrong) {
+          assertStrongSemantics(func, object);
+        }
+        for (let func of readSloppy) {
+          assertSloppySemantics(func, object);
+        }
+      }
+    }
+  }
+  // The same behaviour should be expected for bad accessor properties on the
+  // prototype chain.
+  for (let object of getObjects()) {
+    object.__proto__ = dummyAccessorProto;
+    for (let func of readStrong) {
+      assertStrongSemantics(func, object);
+    }
+    for (let func of readSloppy) {
+      assertSloppySemantics(func, object);
+    }
+  }
+})();
diff --git a/test/mjsunit/strong/load-property-mutate-backing-store.js b/test/mjsunit/strong/load-property-mutate-backing-store.js
new file mode 100644 (file)
index 0000000..5ed4553
--- /dev/null
@@ -0,0 +1,174 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getSloppyArguments() {
+  return arguments;
+}
+
+function getObjects() {
+  "use strict";
+  return [
+    {},
+    Object(""),
+    [],
+    (function(){}),
+    (class Foo {}),
+    getSloppyArguments(),
+    arguments,
+    new Date(),
+    // TODO(conradw): uncomment once Object.defineProperty is fixed.
+    // new Uint32Array(0)
+  ];
+}
+
+function readFromObjectSloppy(o) {
+    return o.foo;
+}
+
+function readFromObjectKeyedSloppy(o) {
+    return o["foo"];
+}
+
+function readFromObjectKeyedVarSloppy(o) {
+  var a = "foo";
+  return o[a];
+}
+
+function readFromObjectKeyedComputedSloppy(o) {
+  var a = "o";
+  return o["fo" + a];
+}
+
+function readFromObjectStrong(o) {
+  "use strong";
+  return o.foo;
+}
+
+function readFromObjectKeyedStrong(o) {
+  "use strong";
+  return o["foo"];
+}
+
+function readFromObjectKeyedLetStrong(o) {
+  "use strong";
+  let a = "foo";
+  return o[a];
+}
+
+function readFromObjectKeyedComputedStrong(o) {
+  "use strong";
+  let a = "o";
+  return o["fo" + a];
+}
+
+function getDescs(x) {
+  return [
+    {value: x},
+    {configurable: true, enumerable: true, writable: true, value: x},
+    {configurable: true, enumerable: true, get: (function() {return x}) },
+  ];
+}
+
+function assertStrongSemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  %OptimizeFunctionOnNextCall(func);
+  assertThrows(function(){func(object)}, TypeError);
+  %DeoptimizeFunction(func);
+  assertThrows(function(){func(object)}, TypeError);
+}
+
+function assertSloppySemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  %OptimizeFunctionOnNextCall(func);
+  assertDoesNotThrow(function(){func(object)});
+  %DeoptimizeFunction(func);
+  assertDoesNotThrow(function(){func(object)});
+}
+
+(function () {
+  "use strict";
+
+  let goodKeys = [
+    "foo"
+  ]
+
+  let badKeys = [
+    "bar",
+    "1",
+    "100001",
+    "3000000001",
+    "5000000001"
+  ];
+
+  let values = [
+    "string",
+    1,
+    100001,
+    30000000001,
+    50000000001,
+    NaN,
+    {},
+    undefined
+  ];
+
+  let badAccessorDescs = [
+    { set: (function(){}) },
+    { configurable: true, enumerable: true, set: (function(){}) }
+  ];
+
+  let readSloppy = [
+    readFromObjectSloppy,
+    readFromObjectKeyedSloppy,
+    readFromObjectKeyedVarSloppy,
+    readFromObjectKeyedComputedSloppy
+  ];
+
+  let readStrong = [
+    readFromObjectStrong,
+    readFromObjectKeyedStrong,
+    readFromObjectKeyedLetStrong,
+    readFromObjectKeyedComputedStrong
+  ];
+
+  let dummyProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyProto, key, { value: undefined });
+  }
+
+  // After altering the backing store, accessing a missing property should still
+  // throw.
+  for (let key of badKeys) {
+    for (let value of values) {
+      for (let desc of getDescs(value)) {
+        for (let object of getObjects()) {
+          Object.defineProperty(object, key, desc);
+          for (let func of readStrong) {
+            assertStrongSemantics(func, object);
+          }
+          for (let func of readSloppy) {
+            assertSloppySemantics(func, object);
+          }
+          // Accessing a property which is on the prototype chain of the object
+          // should not throw.
+          object.__proto__ = dummyProto;
+          for (let key of goodKeys) {
+            for (let func of readStrong.concat(readSloppy)) {
+              assertSloppySemantics(func, object);
+            }
+          }
+        }
+      }
+    }
+  }
+})();
diff --git a/test/mjsunit/strong/load-property.js b/test/mjsunit/strong/load-property.js
new file mode 100644 (file)
index 0000000..5c77a3e
--- /dev/null
@@ -0,0 +1,200 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+
+function getSloppyArguments() {
+  return arguments;
+}
+
+function getObjects() {
+  "use strict";
+  return [
+    {},
+    Object(""),
+    [],
+    (function(){}),
+    (class Foo {}),
+    getSloppyArguments(),
+    arguments,
+    new Date(),
+    new Uint32Array(0)
+  ];
+}
+
+function readFromObjectSloppy(o) {
+    return o.foo;
+}
+
+function readFromObjectKeyedSloppy(o) {
+    return o["foo"];
+}
+
+function readFromObjectKeyedVarSloppy(o) {
+  var a = "foo";
+  return o[a];
+}
+
+function readFromObjectKeyedComputedSloppy(o) {
+  var a = "o";
+  return o["fo" + a];
+}
+
+function readFromObjectStrong(o) {
+  "use strong";
+  return o.foo;
+}
+
+function readFromObjectKeyedStrong(o) {
+  "use strong";
+  return o["foo"];
+}
+
+function readFromObjectKeyedLetStrong(o) {
+  "use strong";
+  let a = "foo";
+  return o[a];
+}
+
+function readFromObjectKeyedComputedStrong(o) {
+  "use strong";
+  let a = "o";
+  return o["fo" + a];
+}
+
+function getDescs(x) {
+  return [
+    {value: x},
+    {configurable: true, enumerable: true, writable: true, value: x},
+    {configurable: true, enumerable: true, get: (function() {return x}) },
+  ];
+}
+
+function assertStrongSemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  assertThrows(function(){func(object)}, TypeError);
+  %OptimizeFunctionOnNextCall(func);
+  assertThrows(function(){func(object)}, TypeError);
+  %DeoptimizeFunction(func);
+  assertThrows(function(){func(object)}, TypeError);
+}
+
+function assertSloppySemantics(func, object) {
+  %DeoptimizeFunction(func);
+  %ClearFunctionTypeFeedback(func);
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  assertDoesNotThrow(function(){func(object)});
+  %OptimizeFunctionOnNextCall(func);
+  assertDoesNotThrow(function(){func(object)});
+  %DeoptimizeFunction(func);
+  assertDoesNotThrow(function(){func(object)});
+}
+
+(function () {
+  "use strict";
+
+  let goodKeys = [
+    "foo"
+  ]
+
+  let badKeys = [
+    "bar",
+    "1",
+    "100001",
+    "3000000001",
+    "5000000001"
+  ];
+
+  let values = [
+    "string",
+    1,
+    100001,
+    30000000001,
+    50000000001,
+    NaN,
+    {},
+    undefined
+  ];
+
+  let literals = [0, NaN, true, "string"];
+
+  let badAccessorDescs = [
+    { set: (function(){}) },
+    { configurable: true, enumerable: true, set: (function(){}) }
+  ];
+
+  let readSloppy = [
+    readFromObjectSloppy,
+    readFromObjectKeyedSloppy,
+    readFromObjectKeyedVarSloppy,
+    readFromObjectKeyedComputedSloppy
+  ];
+
+  let readStrong = [
+    readFromObjectStrong,
+    readFromObjectKeyedStrong,
+    readFromObjectKeyedLetStrong,
+    readFromObjectKeyedComputedStrong
+  ];
+
+  let dummyProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyProto, key, { value: undefined });
+  }
+
+  let dummyAccessorProto = {};
+  for (let key of goodKeys) {
+    Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) })
+  }
+
+  // Attempting to access a property on an object with no defined properties
+  // should throw.
+  for (let object of getObjects().concat(literals)) {
+    for (let func of readStrong) {
+      assertStrongSemantics(func, object);
+    }
+    for (let func of readSloppy) {
+      assertSloppySemantics(func, object);
+    }
+  }
+  for (let object of getObjects()) {
+    // Accessing a property which is on the prototype chain of the object should
+    // not throw.
+    object.__proto__ = dummyProto;
+    for (let key of goodKeys) {
+      for (let func of readStrong.concat(readSloppy)) {
+        assertSloppySemantics(func, object);
+      }
+    }
+  }
+  // Properties with accessor descriptors missing 'get' should throw on access.
+  for (let desc of badAccessorDescs) {
+    for (let key of goodKeys) {
+      for (let object of getObjects()) {
+        Object.defineProperty(object, key, desc);
+        for (let func of readStrong) {
+          assertStrongSemantics(func, object);
+        }
+        for (let func of readSloppy) {
+          assertSloppySemantics(func, object);
+        }
+      }
+    }
+  }
+  // The same behaviour should be expected for bad accessor properties on the
+  // prototype chain.
+  for (let object of getObjects()) {
+    object.__proto__ = dummyAccessorProto;
+    for (let func of readStrong) {
+      assertStrongSemantics(func, object);
+    }
+    for (let func of readSloppy) {
+      assertSloppySemantics(func, object);
+    }
+  }
+})();
index bb257cb..524ea6e 100644 (file)
@@ -84,7 +84,7 @@ class JSTypeFeedbackTest : public TypedGraphTest {
 
     Unique<Name> name = Unique<Name>::CreateUninitialized(
         isolate()->factory()->InternalizeUtf8String(string));
-    const Operator* op = javascript()->LoadNamed(name, feedback);
+    const Operator* op = javascript()->LoadNamed(name, feedback, SLOPPY);
     Node* load = graph()->NewNode(op, global, vector, context);
     if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) {
       for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op);
index ae6a594..a31988b 100644 (file)
@@ -650,34 +650,37 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
       NewArrayBuffer(backing_store, sizeof(backing_store));
   ResolvedFeedbackSlot feedback;
   TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
-    Handle<JSTypedArray> array =
-        factory()->NewJSTypedArray(type, buffer, 0, kLength);
-    int const element_size = static_cast<int>(array->element_size());
-
-    Node* key = Parameter(
-        Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
-    Node* base = HeapConstant(array);
-    Node* vector = UndefinedConstant();
-    Node* context = UndefinedConstant();
-    Node* effect = graph()->start();
-    Node* control = graph()->start();
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->LoadProperty(feedback), base, key, vector, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
+    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+      Handle<JSTypedArray> array =
+          factory()->NewJSTypedArray(type, buffer, 0, kLength);
+      int const element_size = static_cast<int>(array->element_size());
 
-    Matcher<Node*> offset_matcher =
-        element_size == 1
-            ? key
-            : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
+      Node* key = Parameter(
+          Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
+      Node* base = HeapConstant(array);
+      Node* vector = UndefinedConstant();
+      Node* context = UndefinedConstant();
+      Node* effect = graph()->start();
+      Node* control = graph()->start();
+      Reduction r = Reduce(
+          graph()->NewNode(javascript()->LoadProperty(feedback, language_mode),
+                           base, key, vector, context, EmptyFrameState(),
+                           EmptyFrameState(), effect, control));
 
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(
-        r.replacement(),
-        IsLoadBuffer(BufferAccess(type),
-                     IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
-                     offset_matcher,
-                     IsNumberConstant(array->byte_length()->Number()), effect,
-                     control));
+      Matcher<Node*> offset_matcher =
+          element_size == 1
+              ? key
+              : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
+
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(
+          r.replacement(),
+          IsLoadBuffer(BufferAccess(type),
+                       IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+                       offset_matcher,
+                       IsNumberConstant(array->byte_length()->Number()), effect,
+                       control));
+    }
   }
 }
 
@@ -689,29 +692,32 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
       NewArrayBuffer(backing_store, sizeof(backing_store));
   ResolvedFeedbackSlot feedback;
   TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
-    Handle<JSTypedArray> array =
-        factory()->NewJSTypedArray(type, buffer, 0, kLength);
-    ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
-
-    int min = random_number_generator()->NextInt(static_cast<int>(kLength));
-    int max = random_number_generator()->NextInt(static_cast<int>(kLength));
-    if (min > max) std::swap(min, max);
-    Node* key = Parameter(Type::Range(min, max, zone()));
-    Node* base = HeapConstant(array);
-    Node* vector = UndefinedConstant();
-    Node* context = UndefinedConstant();
-    Node* effect = graph()->start();
-    Node* control = graph()->start();
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->LoadProperty(feedback), base, key, vector, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
+    TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+      Handle<JSTypedArray> array =
+          factory()->NewJSTypedArray(type, buffer, 0, kLength);
+      ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
 
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(
-        r.replacement(),
-        IsLoadElement(access,
-                      IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
-                      key, effect, control));
+      int min = random_number_generator()->NextInt(static_cast<int>(kLength));
+      int max = random_number_generator()->NextInt(static_cast<int>(kLength));
+      if (min > max) std::swap(min, max);
+      Node* key = Parameter(Type::Range(min, max, zone()));
+      Node* base = HeapConstant(array);
+      Node* vector = UndefinedConstant();
+      Node* context = UndefinedConstant();
+      Node* effect = graph()->start();
+      Node* control = graph()->start();
+      Reduction r = Reduce(
+          graph()->NewNode(javascript()->LoadProperty(feedback, language_mode),
+                           base, key, vector, context, EmptyFrameState(),
+                           EmptyFrameState(), effect, control));
+
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(
+          r.replacement(),
+          IsLoadElement(access,
+                        IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+                        key, effect, control));
+    }
   }
 }
 
@@ -885,14 +891,17 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) {
   Node* effect = graph()->start();
   Node* control = graph()->start();
 
-  for (size_t i = 0; i < arraysize(names); i++) {
-    Unique<Name> name = Unique<Name>::CreateImmovable(names[i]);
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->LoadNamed(name, feedback), global, vector, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    for (size_t i = 0; i < arraysize(names); i++) {
+      Unique<Name> name = Unique<Name>::CreateImmovable(names[i]);
+      Reduction r = Reduce(graph()->NewNode(
+          javascript()->LoadNamed(name, feedback, language_mode), global,
+          vector, context, EmptyFrameState(), EmptyFrameState(), effect,
+          control));
 
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), matches[i]);
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), matches[i]);
+    }
   }
 }