Revert relanded strong property access CL
Reason: Regressions in various benchmarks. Revert "Revert of Revert of [strong] Implement strong mode restrictions on property access (patchset #1 id:1 of https://codereview.chromium.org/1189153002/)" This reverts commit41405c0470
. Revert "X87: Revert of Revert of [strong] Implement strong mode restrictions on property access." This reverts commit48de5f4d6b
. Revert "Fix overlapping KeyedLoadIC bitfield." This reverts commit4e6c956abf
. Revert "MIPS64: Fix 'Revert of Revert of [strong] Implement strong mode restrictions on property access'." This reverts commit74f97b0d2a
. BUG= Review URL: https://codereview.chromium.org/1199493002 Cr-Commit-Position: refs/heads/master@{#29166}
This commit is contained in:
parent
7028e4b531
commit
4ac7be5656
@ -4372,7 +4372,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2435,14 +2435,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2451,10 +2450,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -3000,7 +2998,6 @@ 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
|
||||
@ -3008,8 +3005,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ str(r0, MemOperand(sp, kPointerSize));
|
||||
@ -3062,7 +3058,6 @@ 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
|
||||
@ -3070,8 +3065,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ str(r0, MemOperand(sp, kPointerSize));
|
||||
|
@ -2956,7 +2956,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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3052,10 +3052,9 @@ 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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
@ -3362,9 +3361,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
|
@ -4494,7 +4494,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ Bind(&try_poly_name);
|
||||
|
@ -2091,7 +2091,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(key->value()));
|
||||
__ Mov(LoadDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2103,15 +2103,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
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(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ Mov(LoadDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
@ -2120,10 +2119,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2685,15 +2683,14 @@ 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
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
// - key
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ Poke(x0, kPointerSize);
|
||||
@ -2746,7 +2743,6 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
__ Peek(scratch, kPointerSize);
|
||||
__ Push(x0, scratch);
|
||||
VisitForStackValue(prop->key());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
|
||||
// Stack here:
|
||||
// - home_object
|
||||
@ -2754,8 +2750,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ Poke(x0, kPointerSize);
|
||||
@ -5203,7 +5198,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ Peek(load_name, 2 * kPointerSize);
|
||||
__ Mov(LoadDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ Mov(x1, x0);
|
||||
__ Poke(x1, 2 * kPointerSize);
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), 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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
||||
DCHECK(ToRegister(instr->result()).is(x0));
|
||||
|
@ -1275,12 +1275,17 @@ static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
|
||||
|
||||
|
||||
static void Generate_LoadIC_Slow(MacroAssembler* masm) {
|
||||
NamedLoadHandlerCompiler::GenerateSlow(masm);
|
||||
LoadIC::GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GenerateInitialize(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
|
||||
ElementHandlerCompiler::GenerateLoadSlow(masm);
|
||||
KeyedLoadIC::GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -1290,12 +1295,7 @@ static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
|
||||
KeyedLoadIC::GenerateMegamorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,11 +86,9 @@ 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) \
|
||||
\
|
||||
@ -106,6 +104,7 @@ 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) \
|
||||
@ -127,13 +126,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) \
|
||||
|
@ -13,44 +13,35 @@ namespace internal {
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode,
|
||||
LanguageMode language_mode) {
|
||||
Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) {
|
||||
return Callable(
|
||||
LoadIC::initialize_stub(
|
||||
isolate, LoadICState(mode, language_mode).GetExtraICState()),
|
||||
LoadIC::initialize_stub(isolate, LoadICState(mode).GetExtraICState()),
|
||||
LoadDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::LoadICInOptimizedCode(
|
||||
Isolate* isolate, ContextualMode mode, LanguageMode language_mode,
|
||||
Isolate* isolate, ContextualMode mode,
|
||||
InlineCacheState initialization_state) {
|
||||
auto code = LoadIC::initialize_stub_in_optimized_code(
|
||||
isolate, LoadICState(mode, language_mode).GetExtraICState(),
|
||||
initialization_state);
|
||||
isolate, LoadICState(mode).GetExtraICState(), initialization_state);
|
||||
return Callable(code, LoadWithVectorDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::KeyedLoadIC(Isolate* isolate,
|
||||
LanguageMode language_mode) {
|
||||
ExtraICState state =
|
||||
is_strong(language_mode) ? LoadICState::kStrongModeState : 0;
|
||||
return Callable(KeyedLoadIC::initialize_stub(isolate, state),
|
||||
Callable CodeFactory::KeyedLoadIC(Isolate* isolate) {
|
||||
return Callable(KeyedLoadIC::initialize_stub(isolate),
|
||||
LoadDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
Isolate* isolate, LanguageMode language_mode,
|
||||
InlineCacheState initialization_state) {
|
||||
ExtraICState state =
|
||||
is_strong(language_mode) ? LoadICState::kStrongModeState : 0;
|
||||
Isolate* isolate, InlineCacheState initialization_state) {
|
||||
auto code = KeyedLoadIC::initialize_stub_in_optimized_code(
|
||||
isolate, initialization_state, state);
|
||||
isolate, initialization_state);
|
||||
if (initialization_state != MEGAMORPHIC) {
|
||||
return Callable(code, LoadWithVectorDescriptor(isolate));
|
||||
}
|
||||
|
@ -32,15 +32,12 @@ class Callable final BASE_EMBEDDED {
|
||||
class CodeFactory final {
|
||||
public:
|
||||
// Initial states for ICs.
|
||||
static Callable LoadIC(Isolate* isolate, ContextualMode mode,
|
||||
LanguageMode language_mode);
|
||||
static Callable LoadIC(Isolate* isolate, ContextualMode mode);
|
||||
static Callable LoadICInOptimizedCode(Isolate* isolate, ContextualMode mode,
|
||||
LanguageMode language_mode,
|
||||
InlineCacheState initialization_state);
|
||||
static Callable KeyedLoadIC(Isolate* isolate, LanguageMode language_mode);
|
||||
static Callable KeyedLoadIC(Isolate* isolate);
|
||||
static Callable KeyedLoadICInOptimizedCode(
|
||||
Isolate* isolate, LanguageMode language_mode,
|
||||
InlineCacheState initialization_state);
|
||||
Isolate* isolate, InlineCacheState initialization_state);
|
||||
static Callable CallIC(Isolate* isolate, int argc,
|
||||
CallICState::CallType call_type);
|
||||
static Callable CallICInOptimizedCode(Isolate* isolate, int argc,
|
||||
|
@ -62,7 +62,8 @@ 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);
|
||||
@ -1900,8 +1901,7 @@ HValue* CodeStubGraphBuilder<LoadDictionaryElementStub>::BuildCodeStub() {
|
||||
|
||||
HValue* hash = BuildElementIndexHash(key);
|
||||
|
||||
return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
|
||||
casted_stub()->language_mode());
|
||||
return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
|
||||
}
|
||||
|
||||
|
||||
@ -2015,6 +2015,7 @@ 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());
|
||||
@ -2058,8 +2059,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
|
||||
HValue* hash = BuildElementIndexHash(key);
|
||||
|
||||
Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
|
||||
casted_stub()->language_mode()));
|
||||
Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash));
|
||||
}
|
||||
kind_if.Else();
|
||||
|
||||
@ -2137,8 +2137,10 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
|
||||
hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift));
|
||||
|
||||
HValue* value = BuildUncheckedDictionaryElementLoad(
|
||||
receiver, properties, key, hash, casted_stub()->language_mode());
|
||||
HValue* value = BuildUncheckedDictionaryElementLoad(receiver,
|
||||
properties,
|
||||
key,
|
||||
hash);
|
||||
Push(value);
|
||||
}
|
||||
if_dict_properties.Else();
|
||||
@ -2213,11 +2215,10 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
inline_or_runtime.Else();
|
||||
{
|
||||
// KeyedLookupCache miss; call runtime.
|
||||
Add<HPushArguments>(receiver, key,
|
||||
Add<HConstant>(casted_stub()->language_mode()));
|
||||
Add<HPushArguments>(receiver, key);
|
||||
Push(Add<HCallRuntime>(
|
||||
isolate()->factory()->empty_string(),
|
||||
Runtime::FunctionForId(Runtime::kKeyedGetProperty), 3));
|
||||
Runtime::FunctionForId(Runtime::kKeyedGetProperty), 2));
|
||||
}
|
||||
inline_or_runtime.End();
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ 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(),
|
||||
|
@ -2114,37 +2114,24 @@ class StringCharAtGenerator {
|
||||
|
||||
class LoadDictionaryElementStub : public HydrogenCodeStub {
|
||||
public:
|
||||
explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
|
||||
: HydrogenCodeStub(isolate) {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
explicit LoadDictionaryElementStub(Isolate* isolate)
|
||||
: HydrogenCodeStub(isolate) {}
|
||||
|
||||
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, const LoadICState& state)
|
||||
: HydrogenCodeStub(isolate) {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
|
||||
|
||||
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);
|
||||
@ -2166,7 +2153,7 @@ class LoadICTrampolineStub : public PlatformCodeStub {
|
||||
return static_cast<ExtraICState>(minor_key_);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
LoadICState state() const {
|
||||
return LoadICState(static_cast<ExtraICState>(minor_key_));
|
||||
}
|
||||
@ -2178,8 +2165,8 @@ class LoadICTrampolineStub : public PlatformCodeStub {
|
||||
|
||||
class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
|
||||
public:
|
||||
explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
|
||||
: LoadICTrampolineStub(isolate, state) {}
|
||||
explicit KeyedLoadICTrampolineStub(Isolate* isolate)
|
||||
: LoadICTrampolineStub(isolate, LoadICState(0)) {}
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
|
||||
|
||||
@ -2285,18 +2272,12 @@ class LoadICStub : public PlatformCodeStub {
|
||||
|
||||
class KeyedLoadICStub : public PlatformCodeStub {
|
||||
public:
|
||||
explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
|
||||
: PlatformCodeStub(isolate) {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
explicit KeyedLoadICStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
||||
|
||||
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);
|
||||
@ -2340,9 +2321,6 @@ 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);
|
||||
|
@ -3455,7 +3455,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, language_mode());
|
||||
const Operator* op = javascript()->LoadProperty(feedback);
|
||||
return Record(js_type_feedback_,
|
||||
NewNode(op, object, key, GetFeedbackVector()), feedback.slot());
|
||||
}
|
||||
@ -3464,8 +3464,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,
|
||||
language_mode(), mode);
|
||||
const Operator* op =
|
||||
javascript()->LoadNamed(MakeUnique(name), feedback, mode);
|
||||
return Record(js_type_feedback_, NewNode(op, object, GetFeedbackVector()),
|
||||
feedback.slot());
|
||||
}
|
||||
@ -3490,9 +3490,8 @@ Node* AstGraphBuilder::BuildNamedSuperLoad(
|
||||
Node* receiver, Node* home_object, Handle<Name> name,
|
||||
const ResolvedFeedbackSlot& feedback) {
|
||||
Node* name_node = jsgraph()->Constant(name);
|
||||
Node* language = jsgraph()->Constant(language_mode());
|
||||
const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
Node* value = NewNode(op, receiver, home_object, name_node, language);
|
||||
const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
Node* value = NewNode(op, receiver, home_object, name_node);
|
||||
return Record(js_type_feedback_, value, feedback.slot());
|
||||
}
|
||||
|
||||
@ -3500,10 +3499,9 @@ 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, 4);
|
||||
Node* value = NewNode(op, receiver, home_object, key, language);
|
||||
javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
Node* value = NewNode(op, receiver, home_object, key);
|
||||
return Record(js_type_feedback_, value, feedback.slot());
|
||||
}
|
||||
|
||||
|
@ -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(), p.language_mode(), UNINITIALIZED);
|
||||
Callable callable =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(isolate(), 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(), p.language_mode(), UNINITIALIZED);
|
||||
isolate(), p.contextual_mode(), UNINITIALIZED);
|
||||
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
|
||||
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
|
||||
ReplaceWithStubCall(node, callable, flags);
|
||||
|
@ -190,7 +190,6 @@ 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();
|
||||
}
|
||||
@ -203,26 +202,24 @@ bool operator!=(LoadNamedParameters const& lhs,
|
||||
|
||||
|
||||
size_t hash_value(LoadNamedParameters const& p) {
|
||||
return base::hash_combine(p.name(), p.language_mode(), p.contextual_mode(),
|
||||
p.feedback());
|
||||
return base::hash_combine(p.name(), p.contextual_mode(), p.feedback());
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, LoadNamedParameters const& p) {
|
||||
return os << Brief(*p.name().handle()) << ", " << p.language_mode() << ", "
|
||||
<< p.contextual_mode();
|
||||
return os << Brief(*p.name().handle()) << ", " << p.contextual_mode();
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, LoadPropertyParameters const& p) {
|
||||
return os << p.language_mode();
|
||||
// Nothing special to print.
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(LoadPropertyParameters const& lhs,
|
||||
LoadPropertyParameters const& rhs) {
|
||||
return lhs.language_mode() == rhs.language_mode() &&
|
||||
lhs.feedback() == rhs.feedback();
|
||||
return lhs.feedback() == rhs.feedback();
|
||||
}
|
||||
|
||||
|
||||
@ -239,7 +236,7 @@ const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op) {
|
||||
|
||||
|
||||
size_t hash_value(LoadPropertyParameters const& p) {
|
||||
return base::hash_combine(p.language_mode(), p.feedback());
|
||||
return hash_value(p.feedback());
|
||||
}
|
||||
|
||||
|
||||
@ -462,9 +459,8 @@ const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
|
||||
|
||||
const Operator* JSOperatorBuilder::LoadNamed(
|
||||
const Unique<Name>& name, const ResolvedFeedbackSlot& feedback,
|
||||
LanguageMode language_mode, ContextualMode contextual_mode) {
|
||||
LoadNamedParameters parameters(name, feedback, language_mode,
|
||||
contextual_mode);
|
||||
ContextualMode contextual_mode) {
|
||||
LoadNamedParameters parameters(name, feedback, contextual_mode);
|
||||
return new (zone()) Operator1<LoadNamedParameters>( // --
|
||||
IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode
|
||||
"JSLoadNamed", // name
|
||||
@ -474,8 +470,8 @@ const Operator* JSOperatorBuilder::LoadNamed(
|
||||
|
||||
|
||||
const Operator* JSOperatorBuilder::LoadProperty(
|
||||
const ResolvedFeedbackSlot& feedback, LanguageMode language_mode) {
|
||||
LoadPropertyParameters parameters(feedback, language_mode);
|
||||
const ResolvedFeedbackSlot& feedback) {
|
||||
LoadPropertyParameters parameters(feedback);
|
||||
return new (zone()) Operator1<LoadPropertyParameters>( // --
|
||||
IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
|
||||
"JSLoadProperty", // name
|
||||
|
@ -223,15 +223,10 @@ class LoadNamedParameters final {
|
||||
public:
|
||||
LoadNamedParameters(const Unique<Name>& name,
|
||||
const ResolvedFeedbackSlot& feedback,
|
||||
LanguageMode language_mode,
|
||||
ContextualMode contextual_mode)
|
||||
: name_(name),
|
||||
feedback_(feedback),
|
||||
language_mode_(language_mode),
|
||||
contextual_mode_(contextual_mode) {}
|
||||
: name_(name), feedback_(feedback), 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_; }
|
||||
@ -239,7 +234,6 @@ class LoadNamedParameters final {
|
||||
private:
|
||||
const Unique<Name> name_;
|
||||
const ResolvedFeedbackSlot feedback_;
|
||||
const LanguageMode language_mode_;
|
||||
const ContextualMode contextual_mode_;
|
||||
};
|
||||
|
||||
@ -257,17 +251,13 @@ const LoadNamedParameters& LoadNamedParametersOf(const Operator* op);
|
||||
// used as a parameter by JSLoadProperty operators.
|
||||
class LoadPropertyParameters final {
|
||||
public:
|
||||
explicit LoadPropertyParameters(const ResolvedFeedbackSlot& feedback,
|
||||
LanguageMode language_mode)
|
||||
: feedback_(feedback), language_mode_(language_mode) {}
|
||||
explicit LoadPropertyParameters(const ResolvedFeedbackSlot& feedback)
|
||||
: feedback_(feedback) {}
|
||||
|
||||
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&);
|
||||
@ -378,11 +368,9 @@ class JSOperatorBuilder final : public ZoneObject {
|
||||
|
||||
const Operator* CallConstruct(int arguments);
|
||||
|
||||
const Operator* LoadProperty(const ResolvedFeedbackSlot& feedback,
|
||||
LanguageMode language_mode);
|
||||
const Operator* LoadProperty(const ResolvedFeedbackSlot& feedback);
|
||||
const Operator* LoadNamed(const Unique<Name>& name,
|
||||
const ResolvedFeedbackSlot& feedback,
|
||||
LanguageMode language_mode,
|
||||
ContextualMode contextual_mode = NOT_CONTEXTUAL);
|
||||
|
||||
const Operator* StoreProperty(LanguageMode language_mode);
|
||||
|
@ -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(), SLOPPY, access.mode()),
|
||||
global, vector, context, state1, state2, global, check_true);
|
||||
javascript()->LoadNamed(name, access.feedback(), 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;
|
||||
|
@ -469,10 +469,8 @@ 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, language_mode).code();
|
||||
Handle<Code> ic = CodeFactory::LoadIC(isolate(), contextual_mode).code();
|
||||
CallIC(ic, id);
|
||||
}
|
||||
|
||||
|
@ -683,7 +683,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void CallIC(Handle<Code> code,
|
||||
TypeFeedbackId id = TypeFeedbackId::None());
|
||||
|
||||
void CallLoadIC(ContextualMode mode, LanguageMode language_mode = SLOPPY,
|
||||
void CallLoadIC(ContextualMode mode,
|
||||
TypeFeedbackId id = TypeFeedbackId::None());
|
||||
void CallGlobalLoadIC(Handle<String> name);
|
||||
void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
|
||||
|
@ -6392,9 +6392,8 @@ class HLoadNamedField final : public HTemplateInstruction<2> {
|
||||
|
||||
class HLoadNamedGeneric final : public HTemplateInstruction<2> {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
|
||||
Handle<Object>, LanguageMode,
|
||||
InlineCacheState);
|
||||
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadNamedGeneric, HValue*,
|
||||
Handle<Object>, InlineCacheState);
|
||||
|
||||
HValue* context() const { return OperandAt(0); }
|
||||
HValue* object() const { return OperandAt(1); }
|
||||
@ -6422,15 +6421,11 @@ 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);
|
||||
@ -6441,7 +6436,6 @@ class HLoadNamedGeneric final : public HTemplateInstruction<2> {
|
||||
Handle<Object> name_;
|
||||
Handle<TypeFeedbackVector> feedback_vector_;
|
||||
FeedbackVectorICSlot slot_;
|
||||
LanguageMode language_mode_;
|
||||
InlineCacheState initialization_state_;
|
||||
};
|
||||
|
||||
@ -6681,9 +6675,8 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
|
||||
class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
|
||||
HValue*, LanguageMode,
|
||||
InlineCacheState);
|
||||
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadKeyedGeneric, HValue*,
|
||||
HValue*, InlineCacheState);
|
||||
HValue* object() const { return OperandAt(0); }
|
||||
HValue* key() const { return OperandAt(1); }
|
||||
HValue* context() const { return OperandAt(2); }
|
||||
@ -6715,15 +6708,11 @@ 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),
|
||||
language_mode_(language_mode) {
|
||||
initialization_state_(initialization_state) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, key);
|
||||
@ -6734,7 +6723,6 @@ class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
|
||||
Handle<TypeFeedbackVector> feedback_vector_;
|
||||
FeedbackVectorICSlot slot_;
|
||||
InlineCacheState initialization_state_;
|
||||
LanguageMode language_mode_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -683,11 +683,6 @@ 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()) { \
|
||||
@ -1672,9 +1667,10 @@ HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
|
||||
}
|
||||
|
||||
|
||||
HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
HValue* receiver, HValue* elements, HValue* key, HValue* hash,
|
||||
LanguageMode language_mode) {
|
||||
HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
|
||||
HValue* elements,
|
||||
HValue* key,
|
||||
HValue* hash) {
|
||||
HValue* capacity =
|
||||
Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
|
||||
nullptr, FAST_ELEMENTS);
|
||||
@ -1716,10 +1712,10 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
{
|
||||
// element == undefined means "not found". Call the runtime.
|
||||
// TODO(jkummerow): walk the prototype chain instead.
|
||||
Add<HPushArguments>(receiver, key, Add<HConstant>(language_mode));
|
||||
Add<HPushArguments>(receiver, key);
|
||||
Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
||||
Runtime::FunctionForId(Runtime::kKeyedGetProperty),
|
||||
3));
|
||||
2));
|
||||
}
|
||||
if_undefined.Else();
|
||||
{
|
||||
@ -1776,10 +1772,10 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
result_index->ClearFlag(HValue::kCanOverflow);
|
||||
Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
|
||||
details_compare.Else();
|
||||
Add<HPushArguments>(receiver, key, Add<HConstant>(language_mode));
|
||||
Add<HPushArguments>(receiver, key);
|
||||
Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
||||
Runtime::FunctionForId(Runtime::kKeyedGetProperty),
|
||||
3));
|
||||
2));
|
||||
details_compare.End();
|
||||
|
||||
found_key_match.Else();
|
||||
@ -6224,7 +6220,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
|
||||
if (IsFound()) return IsLoad() || !IsReadOnly();
|
||||
if (IsIntegerIndexedExotic()) return false;
|
||||
if (!LookupInPrototypes()) return false;
|
||||
if (IsLoad()) return !is_strong(builder_->function_language_mode());
|
||||
if (IsLoad()) return true;
|
||||
|
||||
if (IsAccessorConstant()) return true;
|
||||
LookupTransition(*map_, *name_, NONE);
|
||||
@ -7042,14 +7038,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, function_language_mode(), PREMONOMORPHIC);
|
||||
HLoadKeyedGeneric* result =
|
||||
New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
|
||||
result->SetVectorAndSlot(vector, slot);
|
||||
return result;
|
||||
}
|
||||
|
||||
HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
|
||||
object, name, function_language_mode(), PREMONOMORPHIC);
|
||||
HLoadNamedGeneric* result =
|
||||
New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
|
||||
result->SetVectorAndSlot(vector, slot);
|
||||
return result;
|
||||
} else {
|
||||
@ -7068,8 +7064,8 @@ HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
|
||||
HValue* value) {
|
||||
if (access_type == LOAD) {
|
||||
InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
|
||||
HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
|
||||
object, key, function_language_mode(), initial_state);
|
||||
HLoadKeyedGeneric* result =
|
||||
New<HLoadKeyedGeneric>(object, key, initial_state);
|
||||
// HLoadKeyedGeneric with vector ics benefits from being encoded as
|
||||
// MEGAMORPHIC because the vector/slot combo becomes unnecessary.
|
||||
if (initial_state != MEGAMORPHIC) {
|
||||
|
@ -331,7 +331,6 @@ class HGraph final : public ZoneObject {
|
||||
HConstant* GetConstantMinus1();
|
||||
HConstant* GetConstantTrue();
|
||||
HConstant* GetConstantFalse();
|
||||
HConstant* GetConstantBool(bool value);
|
||||
HConstant* GetConstantHole();
|
||||
HConstant* GetConstantNull();
|
||||
HConstant* GetInvalidContext();
|
||||
@ -1353,9 +1352,9 @@ class HGraphBuilder {
|
||||
HValue* key);
|
||||
|
||||
HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
|
||||
HValue* elements, HValue* key,
|
||||
HValue* hash,
|
||||
LanguageMode language_mode);
|
||||
HValue* elements,
|
||||
HValue* key,
|
||||
HValue* hash);
|
||||
|
||||
HValue* BuildRegExpConstructResult(HValue* length,
|
||||
HValue* index,
|
||||
|
@ -4430,7 +4430,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2347,14 +2347,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ push(Immediate(key->value()));
|
||||
__ push(Immediate(Smi::FromInt(language_mode())));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2363,10 +2362,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2896,15 +2894,13 @@ 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
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ mov(Operand(esp, kPointerSize), eax);
|
||||
@ -2954,15 +2950,13 @@ 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
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ mov(Operand(esp, kPointerSize), eax);
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -2952,10 +2952,9 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), instr->name());
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3197,9 +3196,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -16,30 +16,6 @@ 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) {
|
||||
|
@ -161,8 +161,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||
static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register elements,
|
||||
Register scratch1, Register scratch2,
|
||||
Register result, Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Register result, Label* slow) {
|
||||
// Register use:
|
||||
//
|
||||
// receiver - holds the receiver on entry.
|
||||
@ -184,7 +183,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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ AssertFastElements(elements);
|
||||
@ -203,7 +202,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
|
||||
// scratch2: current prototype
|
||||
__ CompareRoot(scratch2, Heap::kNullValueRootIndex);
|
||||
__ b(eq, &absent);
|
||||
__ b(eq, &return_undefined);
|
||||
__ ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -218,14 +217,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ b(ne, slow);
|
||||
__ jmp(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -284,7 +278,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -319,17 +313,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
|
||||
__ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -351,21 +341,16 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -389,8 +374,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3);
|
||||
__ Ret();
|
||||
|
||||
@ -412,7 +396,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4,
|
||||
r3);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
|
||||
|
@ -267,30 +267,6 @@ 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) {
|
||||
|
@ -167,12 +167,11 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||
static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register elements,
|
||||
Register scratch1, Register scratch2,
|
||||
Register result, Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Register result, Label* slow) {
|
||||
DCHECK(!AreAliased(receiver, key, elements, scratch1, scratch2));
|
||||
|
||||
Label check_prototypes, check_next_prototype;
|
||||
Label done, in_bounds, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
// Check for fast array.
|
||||
__ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
@ -192,7 +191,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, &absent);
|
||||
__ JumpIfRoot(scratch2, Heap::kNullValueRootIndex, &return_undefined);
|
||||
__ Ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ Ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -205,14 +204,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ JumpIfNotRoot(elements, Heap::kEmptyFixedArrayRootIndex, slow);
|
||||
__ B(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ B(&done);
|
||||
|
||||
__ Bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -278,7 +272,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ Bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -302,15 +296,10 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -335,15 +324,10 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -351,8 +335,7 @@ static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key,
|
||||
Register receiver, Register scratch1,
|
||||
Register scratch2, Register scratch3,
|
||||
Register scratch4, Register scratch5,
|
||||
Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Label* slow) {
|
||||
DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4,
|
||||
scratch5));
|
||||
|
||||
@ -368,7 +351,7 @@ static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key,
|
||||
__ CheckFastElements(scratch1, scratch2, &check_number_dictionary);
|
||||
|
||||
GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1,
|
||||
result, slow, language_mode);
|
||||
result, slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1,
|
||||
scratch1, scratch2);
|
||||
__ Ret();
|
||||
@ -439,8 +422,7 @@ static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key,
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Label slow, check_name, index_smi, index_name;
|
||||
|
||||
@ -453,14 +435,13 @@ 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,
|
||||
language_mode);
|
||||
GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
|
||||
|
||||
// Slow case.
|
||||
__ Bind(&slow);
|
||||
__ IncrementCounter(masm->isolate()->counters()->keyed_load_generic_slow(), 1,
|
||||
x4, x3);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ Bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
|
||||
|
@ -537,8 +537,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
|
||||
|
||||
|
||||
void ElementHandlerCompiler::CompileElementHandlers(
|
||||
MapHandleList* receiver_maps, CodeHandleList* handlers,
|
||||
LanguageMode language_mode) {
|
||||
MapHandleList* receiver_maps, CodeHandleList* handlers) {
|
||||
for (int i = 0; i < receiver_maps->length(); ++i) {
|
||||
Handle<Map> receiver_map = receiver_maps->at(i);
|
||||
Handle<Code> cached_stub;
|
||||
@ -554,10 +553,8 @@ 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_strong(language_mode);
|
||||
is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
|
||||
*receiver_map == isolate()->get_initial_js_array_map(elements_kind);
|
||||
|
||||
if (receiver_map->has_indexed_interceptor()) {
|
||||
cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode();
|
||||
@ -570,9 +567,7 @@ void ElementHandlerCompiler::CompileElementHandlers(
|
||||
convert_hole_to_undefined).GetCode();
|
||||
} else {
|
||||
DCHECK(elements_kind == DICTIONARY_ELEMENTS);
|
||||
LoadICState state = LoadICState(
|
||||
is_strong(language_mode) ? LoadICState::kStrongModeState : 0);
|
||||
cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode();
|
||||
cached_stub = LoadDictionaryElementStub(isolate()).GetCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,8 +146,6 @@ 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,
|
||||
@ -292,10 +290,8 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
|
||||
virtual ~ElementHandlerCompiler() {}
|
||||
|
||||
void CompileElementHandlers(MapHandleList* receiver_maps,
|
||||
CodeHandleList* handlers,
|
||||
LanguageMode language_mode);
|
||||
CodeHandleList* handlers);
|
||||
|
||||
static void GenerateLoadSlow(MacroAssembler* masm);
|
||||
static void GenerateStoreSlow(MacroAssembler* masm);
|
||||
};
|
||||
}
|
||||
|
@ -16,39 +16,6 @@ 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) {
|
||||
|
@ -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, LanguageMode language_mode) {
|
||||
Label* slow) {
|
||||
// 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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ 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, &absent);
|
||||
__ j(equal, &return_undefined);
|
||||
__ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset));
|
||||
// scratch: elements of current prototype
|
||||
@ -215,14 +215,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ j(not_equal, slow);
|
||||
__ jmp(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ mov(result, masm->isolate()->factory()->undefined_value());
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -268,8 +263,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -291,8 +285,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow);
|
||||
Isolate* isolate = masm->isolate();
|
||||
Counters* counters = isolate->counters();
|
||||
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
|
||||
@ -324,7 +317,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
// Slow case: jump to runtime.
|
||||
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
|
||||
@ -630,7 +623,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -665,7 +658,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -677,10 +670,7 @@ void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ push(ebx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -698,7 +688,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -710,10 +700,7 @@ void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ push(ebx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,7 +88,7 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
Handle<Map> receiver_map, ExtraICState extra_ic_state) {
|
||||
Handle<Map> receiver_map) {
|
||||
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) &&
|
||||
!(is_strong(LoadICState::GetLanguageMode(extra_ic_state)));
|
||||
*receiver_map == isolate->get_initial_js_array_map(elements_kind);
|
||||
|
||||
Handle<Code> stub;
|
||||
if (receiver_map->has_indexed_interceptor()) {
|
||||
stub = LoadIndexedInterceptorStub(isolate).GetCode();
|
||||
@ -113,8 +113,7 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
|
||||
convert_hole_to_undefined).GetCode();
|
||||
} else {
|
||||
stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state))
|
||||
.GetCode();
|
||||
stub = LoadDictionaryElementStub(isolate).GetCode();
|
||||
}
|
||||
return stub;
|
||||
}
|
||||
@ -222,7 +221,7 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
|
||||
MapHandleList* receiver_maps, LanguageMode language_mode) {
|
||||
MapHandleList* receiver_maps) {
|
||||
Isolate* isolate = receiver_maps->at(0)->GetIsolate();
|
||||
DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT);
|
||||
Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
|
||||
@ -233,7 +232,7 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
|
||||
|
||||
CodeHandleList handlers(receiver_maps->length());
|
||||
ElementHandlerCompiler compiler(isolate);
|
||||
compiler.CompileElementHandlers(receiver_maps, &handlers, language_mode);
|
||||
compiler.CompileElementHandlers(receiver_maps, &handlers);
|
||||
PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = ic_compiler.CompilePolymorphic(
|
||||
receiver_maps, &handlers, isolate->factory()->empty_string(),
|
||||
|
@ -32,13 +32,12 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
|
||||
// Keyed
|
||||
static Handle<Code> ComputeKeyedLoadMonomorphicHandler(
|
||||
Handle<Map> receiver_map, ExtraICState extra_ic_state);
|
||||
Handle<Map> receiver_map);
|
||||
|
||||
static Handle<Code> ComputeKeyedStoreMonomorphic(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
static Handle<Code> ComputeKeyedLoadPolymorphic(MapHandleList* receiver_maps,
|
||||
LanguageMode language_mode);
|
||||
static Handle<Code> ComputeKeyedLoadPolymorphic(MapHandleList* receiver_maps);
|
||||
static Handle<Code> ComputeKeyedStorePolymorphic(
|
||||
MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode,
|
||||
LanguageMode language_mode);
|
||||
|
@ -135,9 +135,6 @@ 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);
|
||||
}
|
||||
|
@ -201,24 +201,11 @@ class CompareICState {
|
||||
|
||||
|
||||
class LoadICState final BASE_EMBEDDED {
|
||||
private:
|
||||
class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
|
||||
class LanguageModeBits
|
||||
: public BitField<LanguageMode, ContextualModeBits::kNext, 2> {};
|
||||
STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
|
||||
const ExtraICState state_;
|
||||
|
||||
public:
|
||||
static const uint32_t kNextBitFieldOffset = LanguageModeBits::kNext;
|
||||
|
||||
static const ExtraICState kStrongModeState = STRONG
|
||||
<< LanguageModeBits::kShift;
|
||||
|
||||
explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
|
||||
|
||||
explicit LoadICState(ContextualMode mode, LanguageMode language_mode)
|
||||
: state_(ContextualModeBits::encode(mode) |
|
||||
LanguageModeBits::encode(language_mode)) {}
|
||||
explicit LoadICState(ContextualMode mode)
|
||||
: state_(ContextualModeBits::encode(mode)) {}
|
||||
|
||||
ExtraICState GetExtraICState() const { return state_; }
|
||||
|
||||
@ -226,17 +213,15 @@ 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();
|
||||
}
|
||||
|
||||
static LanguageMode GetLanguageMode(ExtraICState state) {
|
||||
return LoadICState(state).language_mode();
|
||||
}
|
||||
private:
|
||||
class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
|
||||
STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
|
||||
|
||||
const ExtraICState state_;
|
||||
};
|
||||
|
||||
|
||||
|
102
src/ic/ic.cc
102
src/ic/ic.cc
@ -571,14 +571,11 @@ void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
|
||||
|
||||
|
||||
// static
|
||||
Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
|
||||
ExtraICState extra_state) {
|
||||
Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate) {
|
||||
if (FLAG_compiled_keyed_generic_loads) {
|
||||
return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
return KeyedLoadGenericStub(isolate).GetCode();
|
||||
} else {
|
||||
return is_strong(LoadICState::GetLanguageMode(extra_state))
|
||||
? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong()
|
||||
: isolate->builtins()->KeyedLoadIC_Megamorphic();
|
||||
return isolate->builtins()->KeyedLoadIC_Megamorphic();
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,8 +679,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate(), result,
|
||||
Runtime::GetElementOrCharAt(isolate(), object, index, language_mode()),
|
||||
Object);
|
||||
Runtime::GetElementOrCharAt(isolate(), object, index), Object);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -726,9 +722,8 @@ 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, language_mode()), Object);
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
|
||||
Object);
|
||||
if (it.IsFound()) {
|
||||
return result;
|
||||
} else if (!IsUndeclaredGlobal(object)) {
|
||||
@ -920,20 +915,25 @@ Handle<Code> LoadIC::initialize_stub_in_optimized_code(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate,
|
||||
ExtraICState extra_state) {
|
||||
return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) {
|
||||
return KeyedLoadICTrampolineStub(isolate).GetCode();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, State initialization_state, ExtraICState extra_state) {
|
||||
Isolate* isolate, State initialization_state) {
|
||||
if (initialization_state != MEGAMORPHIC) {
|
||||
return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
return KeyedLoadICStub(isolate).GetCode();
|
||||
}
|
||||
return is_strong(LoadICState::GetLanguageMode(extra_state))
|
||||
? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong()
|
||||
: isolate->builtins()->KeyedLoadIC_Megamorphic();
|
||||
switch (initialization_state) {
|
||||
case UNINITIALIZED:
|
||||
return isolate->builtins()->KeyedLoadIC_Initialize();
|
||||
case MEGAMORPHIC:
|
||||
return isolate->builtins()->KeyedLoadIC_Megamorphic();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return Handle<Code>();
|
||||
}
|
||||
|
||||
|
||||
@ -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(), extra_ic_state());
|
||||
return KeyedLoadIC::ChooseMegamorphicStub(isolate());
|
||||
}
|
||||
|
||||
|
||||
@ -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 && !is_strong(language_mode())) {
|
||||
if (kind() == Code::LOAD_IC) {
|
||||
code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
|
||||
receiver_map());
|
||||
// TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
|
||||
@ -1245,8 +1245,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
|
||||
|
||||
if (target_receiver_maps.length() == 0) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
receiver_map, extra_ic_state());
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
@ -1263,8 +1262,7 @@ 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, extra_ic_state());
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
@ -1289,8 +1287,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
|
||||
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
ElementHandlerCompiler compiler(isolate());
|
||||
compiler.CompileElementHandlers(&target_receiver_maps, &handlers,
|
||||
language_mode());
|
||||
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
|
||||
ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
|
||||
return null_handle;
|
||||
}
|
||||
@ -1301,8 +1298,7 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
|
||||
if (MigrateDeprecated(object)) {
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate(), result,
|
||||
Runtime::GetObjectProperty(isolate(), object, key, language_mode()),
|
||||
isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
|
||||
Object);
|
||||
return result;
|
||||
}
|
||||
@ -1350,12 +1346,10 @@ 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, language_mode()),
|
||||
Object);
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
|
||||
Runtime::GetObjectProperty(isolate(), object, key),
|
||||
Object);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2818,7 +2812,6 @@ 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));
|
||||
|
||||
@ -2864,11 +2857,8 @@ 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, language_mode));
|
||||
isolate, result, Object::GetElement(isolate, receiver, index));
|
||||
return *result;
|
||||
}
|
||||
|
||||
@ -2904,36 +2894,6 @@ 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
|
||||
@ -2942,5 +2902,5 @@ static const Address IC_utilities[] = {
|
||||
|
||||
|
||||
Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; }
|
||||
}
|
||||
} // namespace v8::internal
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
32
src/ic/ic.h
32
src/ic/ic.h
@ -18,8 +18,6 @@ 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) \
|
||||
@ -354,19 +352,14 @@ class CallIC : public IC {
|
||||
|
||||
class LoadIC : public IC {
|
||||
public:
|
||||
static ExtraICState ComputeExtraICState(ContextualMode contextual_mode,
|
||||
LanguageMode language_mode) {
|
||||
return LoadICState(contextual_mode, language_mode).GetExtraICState();
|
||||
static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) {
|
||||
return LoadICState(contextual_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);
|
||||
@ -397,7 +390,7 @@ class LoadIC : public IC {
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateNormal(MacroAssembler* masm);
|
||||
static void GenerateSlow(MacroAssembler* masm);
|
||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
@ -444,13 +437,11 @@ class LoadIC : public IC {
|
||||
class KeyedLoadIC : public LoadIC {
|
||||
public:
|
||||
// ExtraICState bits (building on IC)
|
||||
class IcCheckTypeField
|
||||
: public BitField<IcCheckType, LoadICState::kNextBitFieldOffset, 1> {};
|
||||
class IcCheckTypeField : public BitField<IcCheckType, 1, 1> {};
|
||||
|
||||
static ExtraICState ComputeExtraICState(ContextualMode contextual_mode,
|
||||
LanguageMode language_mode,
|
||||
IcCheckType key_type) {
|
||||
return LoadICState(contextual_mode, language_mode).GetExtraICState() |
|
||||
return LoadICState(contextual_mode).GetExtraICState() |
|
||||
IcCheckTypeField::encode(key_type);
|
||||
}
|
||||
|
||||
@ -470,10 +461,9 @@ class KeyedLoadIC : public LoadIC {
|
||||
|
||||
// Code generator routines.
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateSlow(MacroAssembler* masm);
|
||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode languageMode);
|
||||
static void GenerateMegamorphic(MacroAssembler* masm);
|
||||
|
||||
// Bit mask to be tested against bit field for the cases when
|
||||
// generic stub should go into slow case.
|
||||
@ -482,12 +472,10 @@ class KeyedLoadIC : public LoadIC {
|
||||
static const int kSlowCaseBitFieldMask =
|
||||
(1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
static Handle<Code> initialize_stub(Isolate* isolate);
|
||||
static Handle<Code> initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, State initialization_state, ExtraICState extra_state);
|
||||
static Handle<Code> ChooseMegamorphicStub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
Isolate* isolate, State initialization_state);
|
||||
static Handle<Code> ChooseMegamorphicStub(Isolate* isolate);
|
||||
|
||||
static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
|
||||
|
||||
|
@ -16,30 +16,6 @@ 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) {
|
||||
|
@ -163,8 +163,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||
static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register elements,
|
||||
Register scratch1, Register scratch2,
|
||||
Register result, Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Register result, Label* slow) {
|
||||
// Register use:
|
||||
//
|
||||
// receiver - holds the receiver on entry.
|
||||
@ -186,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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ AssertFastElements(elements);
|
||||
@ -204,7 +203,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ lw(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
|
||||
// scratch2: current prototype
|
||||
__ LoadRoot(at, Heap::kNullValueRootIndex);
|
||||
__ Branch(&absent, eq, scratch2, Operand(at));
|
||||
__ Branch(&return_undefined, eq, scratch2, Operand(at));
|
||||
__ lw(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ lw(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -219,14 +218,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ Branch(slow, ne, elements, Operand(at));
|
||||
__ Branch(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -291,7 +285,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -326,16 +320,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
|
||||
__ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -358,20 +349,16 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -395,8 +382,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, a0, a3, t0, v0, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, t0, a3);
|
||||
__ Ret();
|
||||
|
||||
@ -417,7 +403,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, t0,
|
||||
a3);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);
|
||||
|
@ -16,30 +16,6 @@ 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) {
|
||||
|
@ -162,8 +162,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||
static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register elements,
|
||||
Register scratch1, Register scratch2,
|
||||
Register result, Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Register result, Label* slow) {
|
||||
// Register use:
|
||||
//
|
||||
// receiver - holds the receiver on entry.
|
||||
@ -185,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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ AssertFastElements(elements);
|
||||
@ -203,7 +202,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ ld(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
|
||||
// scratch2: current prototype
|
||||
__ LoadRoot(at, Heap::kNullValueRootIndex);
|
||||
__ Branch(&absent, eq, scratch2, Operand(at));
|
||||
__ Branch(&return_undefined, eq, scratch2, Operand(at));
|
||||
__ ld(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ ld(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -218,13 +217,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ Branch(slow, ne, elements, Operand(at));
|
||||
__ Branch(&check_next_prototype);
|
||||
|
||||
__ bind(&absent);
|
||||
if (is_strong(language_mode)) {
|
||||
__ Branch(slow);
|
||||
} else {
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&done);
|
||||
}
|
||||
__ bind(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -288,7 +283,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -323,16 +318,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
|
||||
__ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -355,20 +347,16 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -392,8 +380,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3);
|
||||
__ Ret();
|
||||
|
||||
@ -414,7 +401,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, a4,
|
||||
a3);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);
|
||||
|
@ -16,30 +16,6 @@ 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) {
|
||||
|
@ -167,8 +167,7 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||
static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register elements,
|
||||
Register scratch1, Register scratch2,
|
||||
Register result, Label* slow,
|
||||
LanguageMode language_mode) {
|
||||
Register result, Label* slow) {
|
||||
// Register use:
|
||||
//
|
||||
// receiver - holds the receiver on entry.
|
||||
@ -190,7 +189,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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ AssertFastElements(elements);
|
||||
@ -209,7 +208,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ LoadP(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
|
||||
// scratch2: current prototype
|
||||
__ CompareRoot(scratch2, Heap::kNullValueRootIndex);
|
||||
__ beq(&absent);
|
||||
__ beq(&return_undefined);
|
||||
__ LoadP(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ LoadP(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -224,14 +223,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ bne(slow);
|
||||
__ jmp(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -294,7 +288,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -329,16 +323,13 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
|
||||
__ mr(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -360,20 +351,16 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -397,8 +384,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, r3, r6, r7, r3, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r7, r6);
|
||||
__ Ret();
|
||||
|
||||
@ -420,7 +406,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r7,
|
||||
r6);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, r3, r6, &index_name, &slow);
|
||||
|
@ -261,39 +261,6 @@ 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) {
|
||||
|
@ -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, LanguageMode language_mode) {
|
||||
Label* slow) {
|
||||
// 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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ 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, &absent);
|
||||
__ j(equal, &return_undefined);
|
||||
__ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset));
|
||||
__ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
|
||||
// elements: elements of current prototype
|
||||
@ -225,14 +225,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ j(not_equal, slow);
|
||||
__ jmp(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -279,8 +274,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -302,8 +296,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow);
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
|
||||
__ ret(0);
|
||||
@ -324,7 +317,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
// Slow case: Jump to runtime.
|
||||
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
|
||||
@ -630,7 +623,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -667,7 +660,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -679,10 +672,7 @@ void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -701,7 +691,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -713,10 +703,7 @@ void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,39 +16,6 @@ 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) {
|
||||
|
@ -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, LanguageMode language_mode) {
|
||||
Label* slow) {
|
||||
// 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, absent;
|
||||
Label done, in_bounds, return_undefined;
|
||||
|
||||
__ 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, &absent);
|
||||
__ j(equal, &return_undefined);
|
||||
__ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset));
|
||||
__ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset));
|
||||
// scratch: elements of current prototype
|
||||
@ -215,14 +215,9 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
||||
__ j(not_equal, slow);
|
||||
__ jmp(&check_next_prototype);
|
||||
|
||||
__ 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(&return_undefined);
|
||||
__ mov(result, masm->isolate()->factory()->undefined_value());
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&in_bounds);
|
||||
// Fast case: Do the load.
|
||||
@ -268,8 +263,7 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
LanguageMode language_mode) {
|
||||
void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
@ -291,8 +285,7 @@ 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,
|
||||
language_mode);
|
||||
GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow);
|
||||
Isolate* isolate = masm->isolate();
|
||||
Counters* counters = isolate->counters();
|
||||
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
|
||||
@ -324,7 +317,7 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
||||
__ bind(&slow);
|
||||
// Slow case: jump to runtime.
|
||||
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
|
||||
@ -630,7 +623,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
__ bind(&slow);
|
||||
GenerateSlow(masm);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
}
|
||||
|
||||
|
||||
@ -665,7 +658,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -677,10 +670,7 @@ void LoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ push(ebx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -698,7 +688,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
@ -710,10 +700,7 @@ void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
|
||||
__ push(ebx);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
|
||||
int arg_count = 2;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,8 +375,6 @@ 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") \
|
||||
|
@ -4592,7 +4592,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2412,14 +2412,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ li(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2428,10 +2427,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2977,7 +2975,6 @@ 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,8 +2982,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ sw(v0, MemOperand(sp, kPointerSize));
|
||||
@ -3037,7 +3033,6 @@ 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
|
||||
@ -3045,8 +3040,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ sw(v0, MemOperand(sp, kPointerSize));
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -2966,10 +2966,9 @@ 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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3294,9 +3293,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -4636,7 +4636,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2411,15 +2411,14 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
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(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ li(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2428,10 +2427,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2980,7 +2978,6 @@ 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
|
||||
@ -2988,8 +2985,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ sd(v0, MemOperand(sp, kPointerSize));
|
||||
@ -3040,7 +3036,6 @@ 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
|
||||
@ -3048,8 +3043,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ sd(v0, MemOperand(sp, kPointerSize));
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3085,10 +3085,9 @@ 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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3455,9 +3454,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -1162,18 +1162,17 @@ bool Object::HasSpecificClassOf(String* name) {
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
|
||||
Handle<Name> name,
|
||||
LanguageMode language_mode) {
|
||||
Handle<Name> name) {
|
||||
LookupIterator it(object, name);
|
||||
return GetProperty(&it, language_mode);
|
||||
return GetProperty(&it);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
|
||||
uint32_t index,
|
||||
LanguageMode language_mode) {
|
||||
MaybeHandle<Object> Object::GetElement(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
uint32_t index) {
|
||||
LookupIterator it(isolate, object, index);
|
||||
return GetProperty(&it, language_mode);
|
||||
return GetProperty(&it);
|
||||
}
|
||||
|
||||
|
||||
@ -1190,11 +1189,11 @@ Handle<Object> Object::GetPrototypeSkipHiddenPrototypes(
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
|
||||
const char* name,
|
||||
LanguageMode language_mode) {
|
||||
MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
const char* name) {
|
||||
Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
|
||||
return GetProperty(object, str, language_mode);
|
||||
return GetProperty(object, str);
|
||||
}
|
||||
|
||||
|
||||
@ -6551,11 +6550,10 @@ String* String::GetForwardedInternalizedString() {
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
|
||||
Handle<Name> name,
|
||||
LanguageMode language_mode) {
|
||||
Handle<Name> name) {
|
||||
LookupIterator it =
|
||||
LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
|
||||
return GetProperty(&it, language_mode);
|
||||
return GetProperty(&it);
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,8 +127,7 @@ bool Object::IsPromise(Handle<Object> object) {
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
|
||||
LanguageMode language_mode) {
|
||||
MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
|
||||
for (; it->IsFound(); it->Next()) {
|
||||
switch (it->state()) {
|
||||
case LookupIterator::NOT_FOUND:
|
||||
@ -148,16 +147,16 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
|
||||
}
|
||||
case LookupIterator::ACCESS_CHECK:
|
||||
if (it->HasAccess()) break;
|
||||
return JSObject::GetPropertyWithFailedAccessCheck(it, language_mode);
|
||||
return JSObject::GetPropertyWithFailedAccessCheck(it);
|
||||
case LookupIterator::ACCESSOR:
|
||||
return GetPropertyWithAccessor(it, language_mode);
|
||||
return GetPropertyWithAccessor(it);
|
||||
case LookupIterator::INTEGER_INDEXED_EXOTIC:
|
||||
return ReadAbsentProperty(it, language_mode);
|
||||
return it->factory()->undefined_value();
|
||||
case LookupIterator::DATA:
|
||||
return it->GetDataValue();
|
||||
}
|
||||
}
|
||||
return ReadAbsentProperty(it, language_mode);
|
||||
return it->factory()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
@ -305,8 +304,7 @@ MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetPropertyWithAccessor(
|
||||
LookupIterator* it, LanguageMode language_mode) {
|
||||
MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
|
||||
Isolate* isolate = it->isolate();
|
||||
Handle<Object> structure = it->GetAccessors();
|
||||
Handle<Object> receiver = it->GetReceiver();
|
||||
@ -338,7 +336,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(
|
||||
args.Call(call_fun, v8::Utils::ToLocal(name));
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||
if (result.IsEmpty()) {
|
||||
return ReadAbsentProperty(isolate, receiver, name, language_mode);
|
||||
return isolate->factory()->undefined_value();
|
||||
}
|
||||
Handle<Object> return_value = v8::Utils::OpenHandle(*result);
|
||||
return_value->VerifyApiCallResultType();
|
||||
@ -354,7 +352,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(
|
||||
receiver, Handle<JSReceiver>::cast(getter));
|
||||
}
|
||||
// Getter is not a function.
|
||||
return ReadAbsentProperty(isolate, receiver, it->GetName(), language_mode);
|
||||
return isolate->factory()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
@ -490,11 +488,11 @@ static bool FindAllCanReadHolder(LookupIterator* it) {
|
||||
|
||||
|
||||
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, LanguageMode language_mode) {
|
||||
LookupIterator* it) {
|
||||
Handle<JSObject> checked = it->GetHolder<JSObject>();
|
||||
while (FindAllCanReadHolder(it)) {
|
||||
if (it->state() == LookupIterator::ACCESSOR) {
|
||||
return GetPropertyWithAccessor(it, language_mode);
|
||||
return GetPropertyWithAccessor(it);
|
||||
}
|
||||
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
|
||||
bool done;
|
||||
@ -3225,26 +3223,6 @@ 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(),
|
||||
|
@ -1162,8 +1162,7 @@ class Object {
|
||||
MUST_USE_RESULT static inline MaybeHandle<Smi> ToSmi(Isolate* isolate,
|
||||
Handle<Object> object);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(
|
||||
LookupIterator* it, LanguageMode language_mode = SLOPPY);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it);
|
||||
|
||||
// Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5.
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
|
||||
@ -1179,15 +1178,10 @@ 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> receiver, Handle<Object> name,
|
||||
Isolate* isolate, Handle<Object> reciever, Handle<Object> name,
|
||||
Handle<Object> value, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> RedefineNonconfigurableProperty(
|
||||
Isolate* isolate, Handle<Object> name, Handle<Object> value,
|
||||
@ -1198,17 +1192,16 @@ 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,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
Handle<Object> object, Handle<Name> name);
|
||||
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
|
||||
Isolate* isolate, Handle<Object> object, const char* key,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
const char* key);
|
||||
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
|
||||
Handle<Object> object, Handle<Name> name,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
Handle<Object> object, Handle<Name> name);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
|
||||
LookupIterator* it, LanguageMode language_mode);
|
||||
LookupIterator* it);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
|
||||
|
||||
@ -1221,8 +1214,9 @@ class Object {
|
||||
Handle<Object> value);
|
||||
|
||||
MUST_USE_RESULT static inline MaybeHandle<Object> GetElement(
|
||||
Isolate* isolate, Handle<Object> object, uint32_t index,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
uint32_t index);
|
||||
|
||||
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
|
||||
Isolate* isolate, Handle<Object> receiver);
|
||||
@ -2338,7 +2332,7 @@ class JSObject: public JSReceiver {
|
||||
|
||||
// Used from Object::GetProperty().
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, LanguageMode language_mode);
|
||||
LookupIterator* it);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, Handle<Object> value);
|
||||
|
@ -4612,7 +4612,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2401,14 +2401,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2417,10 +2416,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2992,7 +2990,6 @@ 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
|
||||
@ -3000,8 +2997,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
@ -3051,7 +3047,6 @@ 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
|
||||
@ -3059,8 +3054,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3141,10 +3141,9 @@ 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()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3516,9 +3515,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,7 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, prototype_parent,
|
||||
Runtime::GetObjectProperty(isolate, super_class,
|
||||
isolate->factory()->prototype_string(),
|
||||
SLOPPY));
|
||||
isolate->factory()->prototype_string()));
|
||||
if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
|
||||
@ -245,87 +244,64 @@ RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
|
||||
}
|
||||
|
||||
|
||||
static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
|
||||
Handle<Object> receiver,
|
||||
Handle<JSObject> home_object,
|
||||
Handle<Name> name,
|
||||
LanguageMode language_mode) {
|
||||
static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSObject> home_object, Handle<Name> name) {
|
||||
if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
|
||||
isolate->ReportFailedAccessCheck(home_object);
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
||||
}
|
||||
|
||||
PrototypeIterator iter(isolate, home_object);
|
||||
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
|
||||
if (!proto->IsJSReceiver()) {
|
||||
return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
|
||||
}
|
||||
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
|
||||
|
||||
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
|
||||
Object::GetProperty(&it, language_mode), Object);
|
||||
return result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
|
||||
Handle<Object> receiver,
|
||||
Handle<JSObject> home_object,
|
||||
uint32_t index,
|
||||
LanguageMode language_mode) {
|
||||
static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSObject> home_object,
|
||||
uint32_t index) {
|
||||
if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
|
||||
isolate->ReportFailedAccessCheck(home_object);
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
||||
}
|
||||
|
||||
PrototypeIterator iter(isolate, home_object);
|
||||
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
|
||||
if (!proto->IsJSReceiver()) {
|
||||
Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
|
||||
return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
|
||||
}
|
||||
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
|
||||
|
||||
LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
|
||||
Object::GetProperty(&it, language_mode), Object);
|
||||
return result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 4);
|
||||
DCHECK(args.length() == 3);
|
||||
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);
|
||||
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
LoadFromSuper(isolate, receiver, home_object, name, language_mode));
|
||||
return *result;
|
||||
return LoadFromSuper(isolate, receiver, home_object, name);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 4);
|
||||
DCHECK(args.length() == 3);
|
||||
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)) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
|
||||
index, language_mode));
|
||||
return *result;
|
||||
return LoadElementFromSuper(isolate, receiver, home_object, index);
|
||||
}
|
||||
|
||||
Handle<Name> name;
|
||||
@ -333,15 +309,9 @@ RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
|
||||
Runtime::ToName(isolate, key));
|
||||
// TODO(verwaest): Unify using LookupIterator.
|
||||
if (name->AsArrayIndex(&index)) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
|
||||
index, language_mode));
|
||||
return *result;
|
||||
return LoadElementFromSuper(isolate, receiver, home_object, index);
|
||||
}
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
LoadFromSuper(isolate, receiver, home_object, name, language_mode));
|
||||
return *result;
|
||||
return LoadFromSuper(isolate, receiver, home_object, name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,7 +81,7 @@ static Handle<Object> DebugGetProperty(LookupIterator* it,
|
||||
return it->isolate()->factory()->undefined_value();
|
||||
}
|
||||
MaybeHandle<Object> maybe_result =
|
||||
JSObject::GetPropertyWithAccessor(it, SLOPPY);
|
||||
JSObject::GetPropertyWithAccessor(it);
|
||||
Handle<Object> result;
|
||||
if (!maybe_result.ToHandle(&result)) {
|
||||
result = handle(it->isolate()->pending_exception(), it->isolate());
|
||||
|
@ -26,8 +26,7 @@ static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
|
||||
|
||||
MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
uint32_t index,
|
||||
LanguageMode language_mode) {
|
||||
uint32_t index) {
|
||||
// Handle [] indexing on Strings
|
||||
if (object->IsString() &&
|
||||
index < static_cast<uint32_t>(String::cast(*object)->length())) {
|
||||
@ -35,7 +34,7 @@ MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
|
||||
if (!result->IsUndefined()) return result;
|
||||
}
|
||||
|
||||
return Object::GetElement(isolate, object, index, language_mode);
|
||||
return Object::GetElement(isolate, object, index);
|
||||
}
|
||||
|
||||
|
||||
@ -53,8 +52,7 @@ MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
|
||||
|
||||
MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key,
|
||||
LanguageMode language_mode) {
|
||||
Handle<Object> key) {
|
||||
if (object->IsUndefined() || object->IsNull()) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
@ -65,7 +63,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, language_mode);
|
||||
return GetElementOrCharAt(isolate, object, index);
|
||||
}
|
||||
|
||||
// Convert the key to a name - possibly by calling back into JavaScript.
|
||||
@ -79,112 +77,11 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
|
||||
if (name->AsArrayIndex(&index)) {
|
||||
return GetElementOrCharAt(isolate, object, index);
|
||||
} else {
|
||||
return Object::GetProperty(object, name, language_mode);
|
||||
return Object::GetProperty(object, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key,
|
||||
@ -486,32 +383,122 @@ RUNTIME_FUNCTION(Runtime_ObjectSeal) {
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_GetProperty) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
DCHECK(args.length() == 2);
|
||||
|
||||
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, language_mode));
|
||||
isolate, result, Runtime::GetObjectProperty(isolate, object, key));
|
||||
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() == 3);
|
||||
DCHECK(args.length() == 2);
|
||||
|
||||
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::KeyedGetObjectProperty(isolate, receiver_obj,
|
||||
key_obj, language_mode));
|
||||
isolate, result,
|
||||
Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,8 @@ namespace internal {
|
||||
F(DefineClass, 6, 1) \
|
||||
F(DefineClassMethod, 3, 1) \
|
||||
F(ClassGetSourceCode, 1, 1) \
|
||||
F(LoadFromSuper, 4, 1) \
|
||||
F(LoadKeyedFromSuper, 4, 1) \
|
||||
F(LoadFromSuper, 3, 1) \
|
||||
F(LoadKeyedFromSuper, 3, 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, 3, 1) \
|
||||
F(KeyedGetProperty, 3, 1) \
|
||||
F(GetProperty, 2, 1) \
|
||||
F(KeyedGetProperty, 2, 1) \
|
||||
F(AddNamedProperty, 4, 1) \
|
||||
F(SetProperty, 4, 1) \
|
||||
F(AddElement, 3, 1) \
|
||||
@ -815,20 +815,14 @@ 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,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
Isolate* isolate, Handle<Object> object, uint32_t index);
|
||||
|
||||
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,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> KeyedGetObjectProperty(
|
||||
Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
|
||||
LanguageMode language_mode);
|
||||
Isolate* isolate, Handle<Object> object, Handle<Object> key);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
|
||||
Isolate* isolate, Handle<Object> object);
|
||||
|
@ -4375,7 +4375,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2376,14 +2376,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ Move(LoadDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
@ -2392,10 +2391,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2891,7 +2889,6 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
__ Push(rax);
|
||||
__ Push(Operand(rsp, kPointerSize * 2));
|
||||
__ Push(key->value());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
|
||||
// Stack here:
|
||||
// - home_object
|
||||
@ -2899,8 +2896,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ movp(Operand(rsp, kPointerSize), rax);
|
||||
@ -2950,7 +2946,6 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
__ Push(rax);
|
||||
__ Push(Operand(rsp, kPointerSize * 2));
|
||||
VisitForStackValue(prop->key());
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
|
||||
// Stack here:
|
||||
// - home_object
|
||||
@ -2958,8 +2953,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
|
||||
// - home_object
|
||||
// - key
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ movp(Operand(rsp, kPointerSize), rax);
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -2980,10 +2980,9 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
__ Move(LoadDescriptor::NameRegister(), instr->name());
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3279,9 +3278,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -4090,7 +4090,7 @@ void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
|
||||
EmitLoadTypeFeedbackVector(masm, LoadWithVectorDescriptor::VectorRegister());
|
||||
KeyedLoadICStub stub(isolate(), state());
|
||||
KeyedLoadICStub stub(isolate());
|
||||
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(), GetExtraICState());
|
||||
KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
|
||||
__ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
|
@ -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(), SLOPPY).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).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, language_mode());
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2338,14 +2338,13 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
__ push(Immediate(key->value()));
|
||||
__ push(Immediate(Smi::FromInt(language_mode())));
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
@ -2354,10 +2353,9 @@ 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, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
}
|
||||
|
||||
|
||||
@ -2887,15 +2885,13 @@ 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
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ mov(Operand(esp, kPointerSize), eax);
|
||||
@ -2945,15 +2941,13 @@ 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
|
||||
// - language_mode
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ mov(Operand(esp, kPointerSize), eax);
|
||||
|
@ -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, SLOPPY,
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3226,10 +3226,9 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), instr->name());
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic =
|
||||
CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL, instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3468,9 +3467,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
|
||||
}
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->language_mode(),
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
isolate(), instr->hydrogen()->initialization_state()).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -19356,7 +19356,7 @@ TEST(AccessCheckThrows) {
|
||||
CheckCorrectThrow("other[1]");
|
||||
CheckCorrectThrow("JSON.stringify(other)");
|
||||
CheckCorrectThrow("has_own_property(other, 'x')");
|
||||
CheckCorrectThrow("%GetProperty(other, 'x', 0)");
|
||||
CheckCorrectThrow("%GetProperty(other, 'x')");
|
||||
CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
|
||||
CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
|
||||
CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
|
||||
|
@ -47,8 +47,8 @@ function* g() {}
|
||||
(function LexicalBindings(global) {
|
||||
assertEquals('function', typeof f);
|
||||
assertEquals('function', typeof g);
|
||||
assertFalse(global.hasOwnProperty("f"));
|
||||
assertFalse(global.hasOwnProperty("g"));
|
||||
assertEquals(undefined, global.f);
|
||||
assertEquals(undefined, global.g);
|
||||
})(this);
|
||||
|
||||
(function ImmutableBindings() {
|
||||
|
@ -1,42 +0,0 @@
|
||||
// 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});
|
||||
})();
|
@ -1,239 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
@ -1,264 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
})();
|
@ -1,174 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
@ -1,200 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
})();
|
@ -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, SLOPPY);
|
||||
const Operator* op = javascript()->LoadNamed(name, feedback);
|
||||
Node* load = graph()->NewNode(op, global, vector, context);
|
||||
if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) {
|
||||
for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op);
|
||||
|
@ -650,37 +650,34 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
|
||||
NewArrayBuffer(backing_store, sizeof(backing_store));
|
||||
ResolvedFeedbackSlot feedback;
|
||||
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
|
||||
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());
|
||||
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, language_mode),
|
||||
base, key, vector, context, EmptyFrameState(),
|
||||
EmptyFrameState(), effect, control));
|
||||
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));
|
||||
|
||||
Matcher<Node*> offset_matcher =
|
||||
element_size == 1
|
||||
? key
|
||||
: IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,32 +689,29 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
|
||||
NewArrayBuffer(backing_store, sizeof(backing_store));
|
||||
ResolvedFeedbackSlot feedback;
|
||||
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
|
||||
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
|
||||
Handle<JSTypedArray> array =
|
||||
factory()->NewJSTypedArray(type, buffer, 0, kLength);
|
||||
ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
|
||||
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, language_mode),
|
||||
base, key, vector, context, EmptyFrameState(),
|
||||
EmptyFrameState(), 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), 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));
|
||||
}
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsLoadElement(access,
|
||||
IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
key, effect, control));
|
||||
}
|
||||
}
|
||||
|
||||
@ -891,17 +885,14 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) {
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), matches[i]);
|
||||
}
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), matches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user