We need to know if a load, store or call IC is assumed
to be on the global object. Previously, this information was stored in RelocInfo. A more logical place for this kind of structural information is ExtraICState. Storing it there makes it easier for us to gather type feedback from these sites too. R=verwaest@chromium.org Review URL: https://codereview.chromium.org/96083005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18466 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
22eff6f87a
commit
e3e7daf01c
@ -659,7 +659,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
|
||||
CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
|
||||
__ tst(result_register(), result_register());
|
||||
Split(ne, if_true, if_false, fall_through);
|
||||
}
|
||||
@ -1020,7 +1020,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
Label skip;
|
||||
@ -1388,11 +1388,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(var->name()));
|
||||
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, mode);
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
CallLoadIC(mode);
|
||||
}
|
||||
|
||||
|
||||
@ -1475,8 +1474,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// object (receiver) in r0.
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(var->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(r0);
|
||||
break;
|
||||
}
|
||||
@ -1685,10 +1683,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ mov(r2, Operand(key->value()));
|
||||
__ ldr(r1, MemOperand(sp));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
} else {
|
||||
VisitForEffect(value);
|
||||
@ -2096,8 +2091,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_loop);
|
||||
__ push(r0); // save result
|
||||
__ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done"
|
||||
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(done_ic); // result.done in r0
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in r0
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ cmp(r0, Operand(0));
|
||||
@ -2106,8 +2100,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(r0); // result
|
||||
__ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
|
||||
Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(value_ic); // result.value in r0
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in r0
|
||||
context()->DropAndPlug(2, r0); // drop iter and g
|
||||
break;
|
||||
}
|
||||
@ -2257,8 +2250,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ mov(r2, Operand(key->value()));
|
||||
// Call load IC. It has arguments receiver and property name r0 and r2.
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2266,7 +2258,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2293,7 +2285,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
|
||||
__ bind(&stub_call);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ jmp(&done);
|
||||
@ -2371,7 +2363,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
||||
__ pop(r1);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
context()->Plug(r0);
|
||||
@ -2410,10 +2402,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
||||
__ mov(r1, r0);
|
||||
__ pop(r0); // Restore value.
|
||||
__ mov(r2, Operand(prop->key()->AsLiteral()->value()));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic);
|
||||
CallStoreIC(NOT_CONTEXTUAL);
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
@ -2439,11 +2428,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
// Global var, const, or let.
|
||||
__ mov(r2, Operand(var->name()));
|
||||
__ ldr(r1, GlobalObjectOperand());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
|
||||
CallStoreIC(CONTEXTUAL);
|
||||
} else if (op == Token::INIT_CONST) {
|
||||
// Const initializers need a write barrier.
|
||||
ASSERT(!var->IsParameter()); // No const parameters.
|
||||
@ -2537,10 +2522,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
__ mov(r2, Operand(prop->key()->AsLiteral()->value()));
|
||||
__ pop(r1);
|
||||
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(r0);
|
||||
@ -2557,7 +2539,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(r0);
|
||||
@ -2584,17 +2566,19 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::CallIC(Handle<Code> code,
|
||||
RelocInfo::Mode rmode,
|
||||
ContextualMode mode,
|
||||
TypeFeedbackId ast_id) {
|
||||
ic_total_count_++;
|
||||
// All calls must have a predictable size in full-codegen code to ensure that
|
||||
// the debugger can patch them correctly.
|
||||
__ Call(code, rmode, ast_id, al, NEVER_INLINE_TARGET_ADDRESS);
|
||||
ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
|
||||
__ Call(code, RelocInfo::CODE_TARGET, ast_id, al,
|
||||
NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> name,
|
||||
RelocInfo::Mode mode) {
|
||||
ContextualMode mode) {
|
||||
// Code common for calls using the IC.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -2609,7 +2593,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallFeedbackId());
|
||||
TypeFeedbackId ast_id = mode == CONTEXTUAL
|
||||
? TypeFeedbackId::None()
|
||||
: expr->CallFeedbackId();
|
||||
CallIC(ic, mode, ast_id);
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
@ -2642,7 +2629,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
|
||||
__ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
@ -2759,7 +2746,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Push global object as receiver for the call IC.
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ push(r0);
|
||||
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
||||
EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
Label slow, done;
|
||||
@ -2806,7 +2793,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
if (property->key()->IsPropertyName()) {
|
||||
EmitCallWithIC(expr,
|
||||
property->key()->AsLiteral()->value(),
|
||||
RelocInfo::CODE_TARGET);
|
||||
NOT_CONTEXTUAL);
|
||||
} else {
|
||||
EmitKeyedCallWithIC(expr, property->key());
|
||||
}
|
||||
@ -4149,7 +4136,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
if (expr->is_jsruntime()) {
|
||||
// Call the JS runtime function.
|
||||
__ mov(r2, Operand(expr->name()));
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
ContextualMode mode = NOT_CONTEXTUAL;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallRuntimeFeedbackId());
|
||||
@ -4400,7 +4387,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
|
||||
BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);
|
||||
CallIC(stub.GetCode(isolate()),
|
||||
RelocInfo::CODE_TARGET,
|
||||
NOT_CONTEXTUAL,
|
||||
expr->CountBinOpFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ bind(&done);
|
||||
@ -4430,10 +4417,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
case NAMED_PROPERTY: {
|
||||
__ mov(r2, Operand(prop->key()->AsLiteral()->value()));
|
||||
__ pop(r1);
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4449,7 +4433,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4472,10 +4456,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(proxy->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallIC(ic);
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
context()->Plug(r0);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
@ -4640,7 +4623,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
__ cmp(r0, Operand::Zero());
|
||||
@ -4675,7 +4658,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else {
|
||||
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
__ cmp(r0, Operand(0));
|
||||
Split(ne, if_true, if_false, fall_through);
|
||||
}
|
||||
|
@ -647,7 +647,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
@ -655,8 +655,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
|
||||
// Probe the stub cache.
|
||||
ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::HANDLER, MONOMORPHIC, kNoExtraICState,
|
||||
Code::HANDLER, MONOMORPHIC, extra_ic_state,
|
||||
Code::NORMAL, Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, r0, r2, r3, r4, r5, r6);
|
||||
|
@ -2958,10 +2958,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, mode, instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -2996,10 +2995,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(r0));
|
||||
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -3092,7 +3091,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
// Name is always in r2.
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
@ -3976,11 +3975,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL);
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
|
||||
@ -4008,11 +4006,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL);
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
|
||||
@ -4209,9 +4206,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
|
||||
// Name is always in r2.
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
|
||||
|
@ -766,8 +766,6 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
|
||||
return "embedded object";
|
||||
case RelocInfo::CONSTRUCT_CALL:
|
||||
return "code target (js construct call)";
|
||||
case RelocInfo::CODE_TARGET_CONTEXT:
|
||||
return "code target (context)";
|
||||
case RelocInfo::DEBUG_BREAK:
|
||||
#ifndef ENABLE_DEBUGGER_SUPPORT
|
||||
UNREACHABLE();
|
||||
@ -862,7 +860,6 @@ void RelocInfo::Verify() {
|
||||
break;
|
||||
#endif
|
||||
case CONSTRUCT_CALL:
|
||||
case CODE_TARGET_CONTEXT:
|
||||
case CODE_TARGET_WITH_ID:
|
||||
case CODE_TARGET: {
|
||||
// convert inline target address to code object
|
||||
|
@ -262,7 +262,6 @@ class RelocInfo BASE_EMBEDDED {
|
||||
CODE_TARGET, // Code target which is not any of the above.
|
||||
CODE_TARGET_WITH_ID,
|
||||
CONSTRUCT_CALL, // code target that is a call to a JavaScript constructor.
|
||||
CODE_TARGET_CONTEXT, // Code target used for contextual loads and stores.
|
||||
DEBUG_BREAK, // Code target for the debugger statement.
|
||||
EMBEDDED_OBJECT,
|
||||
CELL,
|
||||
|
@ -1300,26 +1300,11 @@ BUILTIN(HandleApiCallAsConstructor) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
|
||||
LoadIC::GenerateInitialize(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
|
||||
LoadIC::GeneratePreMonomorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_Miss(MacroAssembler* masm) {
|
||||
LoadIC::GenerateMiss(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
|
||||
LoadIC::GenerateMegamorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_Normal(MacroAssembler* masm) {
|
||||
LoadIC::GenerateNormal(masm);
|
||||
}
|
||||
@ -1381,26 +1366,6 @@ static void Generate_StoreIC_Slow(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
|
||||
StoreIC::GenerateInitialize(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Initialize_Strict(MacroAssembler* masm) {
|
||||
StoreIC::GenerateInitialize(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_PreMonomorphic(MacroAssembler* masm) {
|
||||
StoreIC::GeneratePreMonomorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
|
||||
StoreIC::GeneratePreMonomorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Miss(MacroAssembler* masm) {
|
||||
StoreIC::GenerateMiss(masm);
|
||||
}
|
||||
@ -1411,33 +1376,11 @@ static void Generate_StoreIC_Normal(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
|
||||
StoreIC::GenerateMegamorphic(masm,
|
||||
StoreIC::ComputeExtraICState(kNonStrictMode));
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
|
||||
StoreIC::GenerateMegamorphic(masm,
|
||||
StoreIC::ComputeExtraICState(kStrictMode));
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
|
||||
StoreStubCompiler::GenerateStoreViaSetter(masm, Handle<JSFunction>());
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Generic(MacroAssembler* masm) {
|
||||
StoreIC::GenerateRuntimeSetProperty(masm, kNonStrictMode);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Generic_Strict(MacroAssembler* masm) {
|
||||
StoreIC::GenerateRuntimeSetProperty(masm, kStrictMode);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
|
||||
KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
|
||||
}
|
||||
|
@ -125,15 +125,8 @@ enum BuiltinExtraArguments {
|
||||
kNoExtraICState) \
|
||||
V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, \
|
||||
kNoExtraICState) \
|
||||
V(LoadIC_Initialize, LOAD_IC, UNINITIALIZED, \
|
||||
kNoExtraICState) \
|
||||
V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
\
|
||||
V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED, \
|
||||
kNoExtraICState) \
|
||||
V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC, \
|
||||
@ -147,22 +140,6 @@ enum BuiltinExtraArguments {
|
||||
V(KeyedLoadIC_NonStrictArguments, KEYED_LOAD_IC, MONOMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
\
|
||||
V(StoreIC_Initialize, STORE_IC, UNINITIALIZED, \
|
||||
kNoExtraICState) \
|
||||
V(StoreIC_PreMonomorphic, STORE_IC, PREMONOMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
V(StoreIC_Megamorphic, STORE_IC, MEGAMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
V(StoreIC_Generic, STORE_IC, GENERIC, \
|
||||
kNoExtraICState) \
|
||||
V(StoreIC_Generic_Strict, STORE_IC, GENERIC, \
|
||||
StoreIC::kStrictModeState) \
|
||||
V(StoreIC_Initialize_Strict, STORE_IC, UNINITIALIZED, \
|
||||
StoreIC::kStrictModeState) \
|
||||
V(StoreIC_PreMonomorphic_Strict, STORE_IC, PREMONOMORPHIC, \
|
||||
StoreIC::kStrictModeState) \
|
||||
V(StoreIC_Megamorphic_Strict, STORE_IC, MEGAMORPHIC, \
|
||||
StoreIC::kStrictModeState) \
|
||||
V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, \
|
||||
StoreIC::kStrictModeState) \
|
||||
\
|
||||
|
@ -1053,8 +1053,8 @@ class KeyedArrayCallStub: public HICStub {
|
||||
}
|
||||
|
||||
class ContextualBits: public BitField<bool, 0, 1> {};
|
||||
STATIC_ASSERT(CallICBase::Contextual::kShift == ContextualBits::kShift);
|
||||
STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize);
|
||||
STATIC_ASSERT(IC::Contextual::kShift == ContextualBits::kShift);
|
||||
STATIC_ASSERT(IC::Contextual::kSize == ContextualBits::kSize);
|
||||
class HoleyBits: public BitField<bool, 1, 1> {};
|
||||
STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2);
|
||||
class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {};
|
||||
|
@ -237,7 +237,7 @@ static int DecodeIt(Isolate* isolate,
|
||||
Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
|
||||
Code::Kind kind = code->kind();
|
||||
if (code->is_inline_cache_stub()) {
|
||||
if (rmode == RelocInfo::CODE_TARGET_CONTEXT) {
|
||||
if (code->IsContextual()) {
|
||||
out.AddFormatted(" contextual,");
|
||||
}
|
||||
InlineCacheState ic_state = code->ic_state();
|
||||
|
@ -440,12 +440,23 @@ void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
|
||||
PrepareForBailoutForId(node->id(), state);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::CallLoadIC(ContextualMode mode, TypeFeedbackId id) {
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallIC(ic, mode, id);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::CallStoreIC(ContextualMode mode, TypeFeedbackId id) {
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode(), mode);
|
||||
CallIC(ic, mode, id);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::RecordJSReturnSite(Call* call) {
|
||||
// We record the offset of the function return so we can rebuild the frame
|
||||
// if the function was inlined, i.e., this is the return address in the
|
||||
|
@ -483,7 +483,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
|
||||
// Platform-specific code sequences for calls
|
||||
void EmitCallWithStub(Call* expr, CallFunctionFlags flags);
|
||||
void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
|
||||
void EmitCallWithIC(Call* expr, Handle<Object> name, ContextualMode mode);
|
||||
void EmitKeyedCallWithIC(Call* expr, Expression* key);
|
||||
|
||||
// Platform-specific code for inline runtime calls.
|
||||
@ -565,9 +565,14 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void EmitKeyedPropertyAssignment(Assignment* expr);
|
||||
|
||||
void CallIC(Handle<Code> code,
|
||||
RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
|
||||
ContextualMode mode = NOT_CONTEXTUAL,
|
||||
TypeFeedbackId id = TypeFeedbackId::None());
|
||||
|
||||
void CallLoadIC(ContextualMode mode,
|
||||
TypeFeedbackId id = TypeFeedbackId::None());
|
||||
void CallStoreIC(ContextualMode mode,
|
||||
TypeFeedbackId id = TypeFeedbackId::None());
|
||||
|
||||
void SetFunctionPosition(FunctionLiteral* fun);
|
||||
void SetReturnPosition(FunctionLiteral* fun);
|
||||
void SetStatementPosition(Statement* stmt);
|
||||
@ -597,6 +602,9 @@ class FullCodeGenerator: public AstVisitor {
|
||||
bool is_eval() { return info_->is_eval(); }
|
||||
bool is_native() { return info_->is_native(); }
|
||||
bool is_classic_mode() { return language_mode() == CLASSIC_MODE; }
|
||||
StrictModeFlag strict_mode() {
|
||||
return is_classic_mode() ? kNonStrictMode : kStrictMode;
|
||||
}
|
||||
LanguageMode language_mode() { return function()->language_mode(); }
|
||||
FunctionLiteral* function() { return info_->function(); }
|
||||
Scope* scope() { return scope_; }
|
||||
|
@ -624,7 +624,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
|
||||
CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
|
||||
__ test(result_register(), result_register());
|
||||
// The stub returns nonzero for true.
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
@ -975,7 +975,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
Label skip;
|
||||
@ -1331,11 +1331,11 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
// load IC call.
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, var->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
CallIC(ic, mode);
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
|
||||
CallLoadIC(mode);
|
||||
}
|
||||
|
||||
|
||||
@ -1415,8 +1415,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// object in eax.
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, var->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(eax);
|
||||
break;
|
||||
}
|
||||
@ -1632,10 +1631,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ mov(ecx, Immediate(key->value()));
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
} else {
|
||||
VisitForEffect(value);
|
||||
@ -2058,19 +2054,17 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ push(eax); // save result
|
||||
__ mov(edx, eax); // result
|
||||
__ mov(ecx, isolate()->factory()->done_string()); // "done"
|
||||
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(done_ic); // result.done in eax
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ test(eax, eax);
|
||||
__ j(zero, &l_try);
|
||||
|
||||
// result.value
|
||||
__ pop(edx); // result
|
||||
__ pop(edx); // result
|
||||
__ mov(ecx, isolate()->factory()->value_string()); // "value"
|
||||
Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(value_ic); // result.value in eax
|
||||
context()->DropAndPlug(2, eax); // drop iter and g
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
|
||||
context()->DropAndPlug(2, eax); // drop iter and g
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2213,15 +2207,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
ASSERT(!key->value()->IsSmi());
|
||||
__ mov(ecx, Immediate(key->value()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2242,7 +2235,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
__ bind(&stub_call);
|
||||
__ mov(eax, ecx);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ jmp(&done, Label::kNear);
|
||||
@ -2328,7 +2321,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
||||
__ pop(edx);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
context()->Plug(eax);
|
||||
@ -2367,10 +2360,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
||||
__ mov(edx, eax);
|
||||
__ pop(eax); // Restore value.
|
||||
__ mov(ecx, prop->key()->AsLiteral()->value());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic);
|
||||
CallStoreIC(NOT_CONTEXTUAL);
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
@ -2397,11 +2387,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
// Global var, const, or let.
|
||||
__ mov(ecx, var->name());
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
|
||||
CallStoreIC(CONTEXTUAL);
|
||||
} else if (op == Token::INIT_CONST) {
|
||||
// Const initializers need a write barrier.
|
||||
ASSERT(!var->IsParameter()); // No const parameters.
|
||||
@ -2495,11 +2481,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(ecx, prop->key()->AsLiteral()->value());
|
||||
__ pop(edx);
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
@ -2518,7 +2500,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(eax);
|
||||
@ -2547,10 +2529,11 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::CallIC(Handle<Code> code,
|
||||
RelocInfo::Mode rmode,
|
||||
ContextualMode mode,
|
||||
TypeFeedbackId ast_id) {
|
||||
ic_total_count_++;
|
||||
__ call(code, rmode, ast_id);
|
||||
ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
|
||||
__ call(code, RelocInfo::CODE_TARGET, ast_id);
|
||||
}
|
||||
|
||||
|
||||
@ -2558,7 +2541,7 @@ void FullCodeGenerator::CallIC(Handle<Code> code,
|
||||
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> name,
|
||||
RelocInfo::Mode mode) {
|
||||
ContextualMode mode) {
|
||||
// Code common for calls using the IC.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -2572,7 +2555,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallFeedbackId());
|
||||
TypeFeedbackId ast_id = mode == CONTEXTUAL
|
||||
? TypeFeedbackId::None()
|
||||
: expr->CallFeedbackId();
|
||||
CallIC(ic, mode, ast_id);
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
||||
@ -2604,7 +2590,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
|
||||
__ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key.
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
||||
@ -2714,8 +2700,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else if (proxy != NULL && proxy->var()->IsUnallocated()) {
|
||||
// Push global object as receiver for the call IC.
|
||||
__ push(GlobalObjectOperand());
|
||||
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
||||
|
||||
EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
Label slow, done;
|
||||
@ -2759,7 +2744,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
if (property->key()->IsPropertyName()) {
|
||||
EmitCallWithIC(expr,
|
||||
property->key()->AsLiteral()->value(),
|
||||
RelocInfo::CODE_TARGET);
|
||||
NOT_CONTEXTUAL);
|
||||
} else {
|
||||
EmitKeyedCallWithIC(expr, property->key());
|
||||
}
|
||||
@ -4150,7 +4135,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
if (expr->is_jsruntime()) {
|
||||
// Call the JS runtime function via a call IC.
|
||||
__ Set(ecx, Immediate(expr->name()));
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
ContextualMode mode = NOT_CONTEXTUAL;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallRuntimeFeedbackId());
|
||||
@ -4410,7 +4395,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ mov(eax, Immediate(Smi::FromInt(1)));
|
||||
BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
|
||||
CallIC(stub.GetCode(isolate()),
|
||||
RelocInfo::CODE_TARGET,
|
||||
NOT_CONTEXTUAL,
|
||||
expr->CountBinOpFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ bind(&done);
|
||||
@ -4442,10 +4427,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
case NAMED_PROPERTY: {
|
||||
__ mov(ecx, prop->key()->AsLiteral()->value());
|
||||
__ pop(edx);
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4462,7 +4444,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
// Result is on the stack
|
||||
@ -4487,10 +4469,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, Immediate(proxy->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallIC(ic);
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
context()->Plug(eax);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
@ -4652,7 +4633,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
@ -4688,7 +4669,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else {
|
||||
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
__ test(eax, eax);
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
}
|
||||
|
@ -1319,7 +1319,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
@ -1327,8 +1327,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
|
||||
// Probe the stub cache.
|
||||
ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::HANDLER, MONOMORPHIC, kNoExtraICState,
|
||||
Code::HANDLER, MONOMORPHIC, extra_ic_state,
|
||||
Code::NORMAL, Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, edx, ecx, ebx, eax);
|
||||
|
@ -3164,10 +3164,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
|
||||
RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, mode, instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -3196,10 +3195,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -3318,7 +3317,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -4228,11 +4227,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL);
|
||||
__ mov(ecx, instr->name());
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -4260,11 +4258,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL);
|
||||
__ mov(ecx, instr->name());
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -4496,9 +4493,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
89
src/ic.cc
89
src/ic.cc
@ -148,6 +148,9 @@ IC::IC(FrameDepth depth, Isolate* isolate)
|
||||
pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
|
||||
target_ = handle(raw_target(), isolate);
|
||||
state_ = target_->ic_state();
|
||||
extra_ic_state_ = target_->needs_extended_extra_ic_state(target_->kind())
|
||||
? target_->extended_extra_ic_state()
|
||||
: target_->extra_ic_state();
|
||||
}
|
||||
|
||||
|
||||
@ -255,9 +258,8 @@ bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
|
||||
argc >= 1 && args[1]->IsNumber()) {
|
||||
double index = DoubleToInteger(args.number_at(1));
|
||||
if (index < 0 || index >= string->length()) {
|
||||
extra_ic_state_ =
|
||||
StringStubState::update(extra_ic_state(),
|
||||
STRING_INDEX_OUT_OF_BOUNDS);
|
||||
set_extra_ic_state(StringStubState::update(extra_ic_state(),
|
||||
STRING_INDEX_OUT_OF_BOUNDS));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -398,19 +400,6 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
|
||||
}
|
||||
|
||||
|
||||
RelocInfo::Mode IC::ComputeMode() {
|
||||
Address addr = address();
|
||||
Code* code = Code::cast(isolate()->FindCodeObject(addr));
|
||||
for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
|
||||
!it.done(); it.next()) {
|
||||
RelocInfo* info = it.rinfo();
|
||||
if (info->pc() == addr) return info->rmode();
|
||||
}
|
||||
UNREACHABLE();
|
||||
return RelocInfo::NONE32;
|
||||
}
|
||||
|
||||
|
||||
Failure* IC::TypeError(const char* type,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key) {
|
||||
@ -500,12 +489,9 @@ void IC::Clear(Isolate* isolate, Address address) {
|
||||
|
||||
void CallICBase::Clear(Address address, Code* target) {
|
||||
if (IsCleared(target)) return;
|
||||
bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
|
||||
Code* code =
|
||||
target->GetIsolate()->stub_cache()->FindCallInitialize(
|
||||
target->arguments_count(),
|
||||
contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
|
||||
target->kind());
|
||||
ContextualMode mode = IC::GetContextualMode(target->extra_ic_state());
|
||||
Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize(
|
||||
target->arguments_count(), mode, target->kind());
|
||||
SetTargetAtAddress(address, code);
|
||||
}
|
||||
|
||||
@ -521,15 +507,17 @@ void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
|
||||
|
||||
void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
|
||||
if (IsCleared(target)) return;
|
||||
SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
|
||||
Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
|
||||
Code::LOAD_IC, target->extra_ic_state());
|
||||
SetTargetAtAddress(address, code);
|
||||
}
|
||||
|
||||
|
||||
void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
|
||||
if (IsCleared(target)) return;
|
||||
SetTargetAtAddress(address,
|
||||
*pre_monomorphic_stub(
|
||||
isolate, StoreIC::GetStrictMode(target->extra_ic_state())));
|
||||
Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
|
||||
Code::STORE_IC, target->extra_ic_state());
|
||||
SetTargetAtAddress(address, code);
|
||||
}
|
||||
|
||||
|
||||
@ -1113,6 +1101,26 @@ void IC::PatchCache(Handle<Type> type,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) {
|
||||
Handle<Code> ic = isolate->stub_cache()->ComputeLoad(
|
||||
UNINITIALIZED, IC::ComputeExtraICState(mode));
|
||||
return ic;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
|
||||
ContextualMode mode) {
|
||||
return isolate->stub_cache()->ComputeLoad(
|
||||
PREMONOMORPHIC, IC::ComputeExtraICState(mode));
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::megamorphic_stub() {
|
||||
return isolate()->stub_cache()->ComputeLoad(
|
||||
MEGAMORPHIC, extra_ic_state());
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::SimpleFieldLoad(int offset,
|
||||
bool inobject,
|
||||
Representation representation) {
|
||||
@ -1590,6 +1598,35 @@ MaybeObject* StoreIC::Store(Handle<Object> object,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode,
|
||||
ContextualMode mode) {
|
||||
ExtraICState extra_state = ComputeExtraICState(strict_mode, mode);
|
||||
Handle<Code> ic = isolate->stub_cache()->ComputeStore(
|
||||
UNINITIALIZED, extra_state);
|
||||
return ic;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreIC::megamorphic_stub() {
|
||||
return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state());
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreIC::generic_stub() const {
|
||||
return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state());
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode,
|
||||
ContextualMode contextual_mode) {
|
||||
ExtraICState state = StoreIC::ComputeExtraICState(strict_mode,
|
||||
contextual_mode);
|
||||
return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
|
||||
}
|
||||
|
||||
|
||||
void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<String> name,
|
||||
|
156
src/ic.h
156
src/ic.h
@ -89,6 +89,20 @@ class IC {
|
||||
EXTRA_CALL_FRAME = 1
|
||||
};
|
||||
|
||||
// ExtraICState shared by all ICs.
|
||||
class Contextual: public BitField<ContextualMode, 0, 1> {};
|
||||
STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
|
||||
static ExtraICState ComputeExtraICState(ContextualMode mode) {
|
||||
return Contextual::encode(mode);
|
||||
}
|
||||
|
||||
static ContextualMode GetContextualMode(ExtraICState state) {
|
||||
return Contextual::decode(state);
|
||||
}
|
||||
|
||||
static const ExtraICState kContextualState =
|
||||
static_cast<int>(CONTEXTUAL) << Contextual::kShift;
|
||||
|
||||
// Construct the IC structure with the given number of extra
|
||||
// JavaScript frames on the stack.
|
||||
IC(FrameDepth depth, Isolate* isolate);
|
||||
@ -106,26 +120,17 @@ class IC {
|
||||
// Clear the inline cache to initial state.
|
||||
static void Clear(Isolate* isolate, Address address);
|
||||
|
||||
// Computes the reloc info for this IC. This is a fairly expensive
|
||||
// operation as it has to search through the heap to find the code
|
||||
// object that contains this IC site.
|
||||
RelocInfo::Mode ComputeMode();
|
||||
|
||||
// Returns if this IC is for contextual (no explicit receiver)
|
||||
// access to properties.
|
||||
bool IsUndeclaredGlobal(Handle<Object> receiver) {
|
||||
if (receiver->IsGlobalObject()) {
|
||||
return SlowIsUndeclaredGlobal();
|
||||
return IsContextual();
|
||||
} else {
|
||||
ASSERT(!SlowIsUndeclaredGlobal());
|
||||
ASSERT(!IsContextual());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SlowIsUndeclaredGlobal() {
|
||||
return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool IsLoadStub() {
|
||||
return target()->is_load_stub() || target()->is_keyed_load_stub();
|
||||
@ -169,6 +174,12 @@ class IC {
|
||||
static Type* MapToType(Handle<Map> type);
|
||||
static Handle<Type> CurrentTypeOf(Handle<Object> object, Isolate* isolate);
|
||||
|
||||
ContextualMode contextual_mode() const {
|
||||
return Contextual::decode(extra_ic_state());
|
||||
}
|
||||
|
||||
bool IsContextual() const { return contextual_mode() == CONTEXTUAL; }
|
||||
|
||||
protected:
|
||||
// Get the call-site target; used for determining the state.
|
||||
Handle<Code> target() const { return target_; }
|
||||
@ -257,7 +268,10 @@ class IC {
|
||||
Handle<String> name);
|
||||
void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
|
||||
|
||||
virtual ExtraICState extra_ic_state() { return kNoExtraICState; }
|
||||
ExtraICState extra_ic_state() const { return extra_ic_state_; }
|
||||
void set_extra_ic_state(ExtraICState state) {
|
||||
extra_ic_state_ = state;
|
||||
}
|
||||
|
||||
private:
|
||||
Code* raw_target() const { return GetTargetAtAddress(address()); }
|
||||
@ -278,6 +292,8 @@ class IC {
|
||||
State state_;
|
||||
bool target_set_;
|
||||
|
||||
ExtraICState extra_ic_state_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
|
||||
};
|
||||
|
||||
@ -307,7 +323,6 @@ enum StringStubFeedback {
|
||||
class CallICBase: public IC {
|
||||
public:
|
||||
// ExtraICState bits
|
||||
class Contextual: public BitField<ContextualMode, 0, 1> {};
|
||||
class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
|
||||
static ExtraICState ComputeExtraICState(ContextualMode mode,
|
||||
StringStubFeedback feedback) {
|
||||
@ -368,8 +383,7 @@ class CallICBase: public IC {
|
||||
class CallIC: public CallICBase {
|
||||
public:
|
||||
explicit CallIC(Isolate* isolate)
|
||||
: CallICBase(Code::CALL_IC, isolate),
|
||||
extra_ic_state_(target()->extra_ic_state()) {
|
||||
: CallICBase(Code::CALL_IC, isolate) {
|
||||
ASSERT(target()->is_call_stub());
|
||||
}
|
||||
|
||||
@ -395,12 +409,6 @@ class CallIC: public CallICBase {
|
||||
GenerateMiss(masm, argc, kNoExtraICState);
|
||||
}
|
||||
bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object);
|
||||
|
||||
protected:
|
||||
virtual ExtraICState extra_ic_state() { return extra_ic_state_; }
|
||||
|
||||
private:
|
||||
ExtraICState extra_ic_state_;
|
||||
};
|
||||
|
||||
|
||||
@ -432,7 +440,8 @@ class KeyedCallIC: public CallICBase {
|
||||
|
||||
class LoadIC: public IC {
|
||||
public:
|
||||
explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
|
||||
explicit LoadIC(FrameDepth depth, Isolate* isolate)
|
||||
: IC(depth, isolate) {
|
||||
ASSERT(IsLoadStub());
|
||||
}
|
||||
|
||||
@ -442,10 +451,12 @@ class LoadIC: public IC {
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateMegamorphic(MacroAssembler* masm);
|
||||
static void GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode);
|
||||
static void GenerateNormal(MacroAssembler* masm);
|
||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate, ContextualMode mode);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
|
||||
Handle<String> name);
|
||||
|
||||
@ -456,9 +467,7 @@ class LoadIC: public IC {
|
||||
return isolate()->builtins()->LoadIC_Slow();
|
||||
}
|
||||
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->LoadIC_Megamorphic();
|
||||
}
|
||||
virtual Handle<Code> megamorphic_stub();
|
||||
|
||||
// Update the inline cache and the global stub cache based on the
|
||||
// lookup result.
|
||||
@ -474,16 +483,11 @@ class LoadIC: public IC {
|
||||
|
||||
private:
|
||||
// Stub accessors.
|
||||
static Handle<Code> initialize_stub(Isolate* isolate) {
|
||||
return isolate->builtins()->LoadIC_Initialize();
|
||||
}
|
||||
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
|
||||
return isolate->builtins()->LoadIC_PreMonomorphic();
|
||||
}
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
|
||||
ContextualMode mode);
|
||||
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
return pre_monomorphic_stub(isolate());
|
||||
return pre_monomorphic_stub(isolate(), contextual_mode());
|
||||
}
|
||||
|
||||
Handle<Code> SimpleFieldLoad(int offset,
|
||||
@ -545,9 +549,6 @@ class KeyedLoadIC: public LoadIC {
|
||||
|
||||
private:
|
||||
// Stub accessors.
|
||||
static Handle<Code> initialize_stub(Isolate* isolate) {
|
||||
return isolate->builtins()->KeyedLoadIC_Initialize();
|
||||
}
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
|
||||
return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
|
||||
}
|
||||
@ -573,11 +574,16 @@ class KeyedLoadIC: public LoadIC {
|
||||
class StoreIC: public IC {
|
||||
public:
|
||||
// ExtraICState bits
|
||||
class StrictModeState: public BitField<StrictModeFlag, 0, 1> {};
|
||||
class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
|
||||
static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
|
||||
return StrictModeState::encode(flag);
|
||||
}
|
||||
|
||||
static ExtraICState ComputeExtraICState(StrictModeFlag flag,
|
||||
ContextualMode mode) {
|
||||
return StrictModeState::encode(flag) | Contextual::encode(mode);
|
||||
}
|
||||
|
||||
static StrictModeFlag GetStrictMode(ExtraICState state) {
|
||||
return StrictModeState::decode(state);
|
||||
}
|
||||
@ -588,12 +594,13 @@ class StoreIC: public IC {
|
||||
1 << StrictModeState::kShift;
|
||||
|
||||
StoreIC(FrameDepth depth, Isolate* isolate)
|
||||
: IC(depth, isolate),
|
||||
strict_mode_(GetStrictMode(target()->extra_ic_state())) {
|
||||
: IC(depth, isolate) {
|
||||
ASSERT(IsStoreStub());
|
||||
}
|
||||
|
||||
StrictModeFlag strict_mode() const { return strict_mode_; }
|
||||
StrictModeFlag strict_mode() const {
|
||||
return StrictModeState::decode(extra_ic_state());
|
||||
}
|
||||
|
||||
// Code generators for stub routines. Only called once at startup.
|
||||
static void GenerateSlow(MacroAssembler* masm);
|
||||
@ -608,6 +615,10 @@ class StoreIC: public IC {
|
||||
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode,
|
||||
ContextualMode mode);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* Store(
|
||||
Handle<Object> object,
|
||||
Handle<String> name,
|
||||
@ -617,38 +628,22 @@ class StoreIC: public IC {
|
||||
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::STORE_IC; }
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
if (strict_mode() == kStrictMode) {
|
||||
return isolate()->builtins()->StoreIC_Megamorphic_Strict();
|
||||
} else {
|
||||
return isolate()->builtins()->StoreIC_Megamorphic();
|
||||
}
|
||||
}
|
||||
virtual Handle<Code> megamorphic_stub();
|
||||
|
||||
// Stub accessors.
|
||||
virtual Handle<Code> generic_stub() const {
|
||||
if (strict_mode() == kStrictMode) {
|
||||
return isolate()->builtins()->StoreIC_Generic_Strict();
|
||||
} else {
|
||||
return isolate()->builtins()->StoreIC_Generic();
|
||||
}
|
||||
}
|
||||
virtual Handle<Code> generic_stub() const;
|
||||
|
||||
virtual Handle<Code> slow_stub() const {
|
||||
return isolate()->builtins()->StoreIC_Slow();
|
||||
}
|
||||
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
return pre_monomorphic_stub(isolate(), strict_mode());
|
||||
return pre_monomorphic_stub(isolate(), strict_mode(), contextual_mode());
|
||||
}
|
||||
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode) {
|
||||
if (strict_mode == kStrictMode) {
|
||||
return isolate->builtins()->StoreIC_PreMonomorphic_Strict();
|
||||
} else {
|
||||
return isolate->builtins()->StoreIC_PreMonomorphic();
|
||||
}
|
||||
}
|
||||
StrictModeFlag strict_mode,
|
||||
ContextualMode contextual_mode);
|
||||
|
||||
// Update the inline cache and the global stub cache based on the
|
||||
// lookup result.
|
||||
@ -662,31 +657,19 @@ class StoreIC: public IC {
|
||||
Handle<Object> value,
|
||||
InlineCacheHolderFlag cache_holder);
|
||||
|
||||
virtual ExtraICState extra_ic_state() {
|
||||
return ComputeExtraICState(strict_mode());
|
||||
}
|
||||
|
||||
private:
|
||||
void set_target(Code* code) {
|
||||
// Strict mode must be preserved across IC patching.
|
||||
ASSERT(GetStrictMode(code->extra_ic_state()) ==
|
||||
GetStrictMode(target()->extra_ic_state()));
|
||||
// As must the contextual mode
|
||||
ASSERT(GetContextualMode(code->extra_ic_state()) ==
|
||||
GetContextualMode(target()->extra_ic_state()));
|
||||
IC::set_target(code);
|
||||
}
|
||||
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode) {
|
||||
if (strict_mode == kStrictMode) {
|
||||
return isolate->builtins()->StoreIC_Initialize_Strict();
|
||||
} else {
|
||||
return isolate->builtins()->StoreIC_Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
static void Clear(Isolate* isolate, Address address, Code* target);
|
||||
|
||||
StrictModeFlag strict_mode_;
|
||||
|
||||
friend class IC;
|
||||
};
|
||||
|
||||
@ -708,10 +691,10 @@ class KeyedStoreIC: public StoreIC {
|
||||
// ExtraICState bits (building on IC)
|
||||
// ExtraICState bits
|
||||
class ExtraICStateKeyedAccessStoreMode:
|
||||
public BitField<KeyedAccessStoreMode, 1, 4> {}; // NOLINT
|
||||
public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT
|
||||
|
||||
static ExtraICState ComputeExtraICState(StrictModeFlag flag,
|
||||
KeyedAccessStoreMode mode) {
|
||||
KeyedAccessStoreMode mode) {
|
||||
return StrictModeState::encode(flag) |
|
||||
ExtraICStateKeyedAccessStoreMode::encode(mode);
|
||||
}
|
||||
@ -747,10 +730,6 @@ class KeyedStoreIC: public StoreIC {
|
||||
|
||||
virtual void UpdateMegamorphicCache(Type* type, Name* name, Code* code) { }
|
||||
|
||||
virtual ExtraICState extra_ic_state() {
|
||||
return ComputeExtraICState(strict_mode(), STANDARD_STORE);
|
||||
}
|
||||
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
return pre_monomorphic_stub(isolate(), strict_mode());
|
||||
}
|
||||
@ -784,15 +763,6 @@ class KeyedStoreIC: public StoreIC {
|
||||
}
|
||||
|
||||
// Stub accessors.
|
||||
static Handle<Code> initialize_stub(Isolate* isolate,
|
||||
StrictModeFlag strict_mode) {
|
||||
if (strict_mode == kStrictMode) {
|
||||
return isolate->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
} else {
|
||||
return isolate->builtins()->KeyedStoreIC_Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
virtual Handle<Code> generic_stub() const {
|
||||
if (strict_mode() == kStrictMode) {
|
||||
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
|
||||
|
@ -119,6 +119,13 @@ struct TickSample;
|
||||
V(CALL_MISS_TAG, "CallMiss") \
|
||||
V(CALL_NORMAL_TAG, "CallNormal") \
|
||||
V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \
|
||||
V(LOAD_INITIALIZE_TAG, "LoadInitialize") \
|
||||
V(LOAD_PREMONOMORPHIC_TAG, "LoadPreMonomorphic") \
|
||||
V(LOAD_MEGAMORPHIC_TAG, "LoadMegamorphic") \
|
||||
V(STORE_INITIALIZE_TAG, "StoreInitialize") \
|
||||
V(STORE_PREMONOMORPHIC_TAG, "StorePreMonomorphic") \
|
||||
V(STORE_GENERIC_TAG, "StoreGeneric") \
|
||||
V(STORE_MEGAMORPHIC_TAG, "StoreMegamorphic") \
|
||||
V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \
|
||||
V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \
|
||||
"KeyedCallDebugPrepareStepIn") \
|
||||
|
@ -672,7 +672,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* fall_through) {
|
||||
__ mov(a0, result_register());
|
||||
Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
|
||||
CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
|
||||
__ mov(at, zero_reg);
|
||||
Split(ne, v0, Operand(at), if_true, if_false, fall_through);
|
||||
}
|
||||
@ -1037,7 +1037,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
Label skip;
|
||||
@ -1400,11 +1400,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
|
||||
__ lw(a0, GlobalObjectOperand());
|
||||
__ li(a2, Operand(var->name()));
|
||||
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, mode);
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
CallLoadIC(mode);
|
||||
}
|
||||
|
||||
|
||||
@ -1487,8 +1486,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// object (receiver) in a0.
|
||||
__ lw(a0, GlobalObjectOperand());
|
||||
__ li(a2, Operand(var->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(v0);
|
||||
break;
|
||||
}
|
||||
@ -1700,10 +1698,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ mov(a0, result_register());
|
||||
__ li(a2, Operand(key->value()));
|
||||
__ lw(a1, MemOperand(sp));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
} else {
|
||||
VisitForEffect(value);
|
||||
@ -2118,8 +2113,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ mov(a0, v0);
|
||||
__ push(a0); // save result
|
||||
__ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done"
|
||||
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(done_ic); // result.done in v0
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in v0
|
||||
__ mov(a0, v0);
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
@ -2128,8 +2122,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(a0); // result
|
||||
__ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value"
|
||||
Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(value_ic); // result.value in v0
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in v0
|
||||
context()->DropAndPlug(2, v0); // drop iter and g
|
||||
break;
|
||||
}
|
||||
@ -2277,8 +2270,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
__ mov(a0, result_register());
|
||||
__ li(a2, Operand(key->value()));
|
||||
// Call load IC. It has arguments receiver and property name a0 and a2.
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2287,7 +2279,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
__ mov(a0, result_register());
|
||||
// Call keyed load IC. It has arguments key and receiver in a0 and a1.
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2315,8 +2307,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
|
||||
__ bind(&stub_call);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ jmp(&done);
|
||||
|
||||
@ -2398,7 +2390,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
||||
__ pop(a1);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
context()->Plug(v0);
|
||||
@ -2437,10 +2429,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
||||
__ mov(a1, result_register());
|
||||
__ pop(a0); // Restore value.
|
||||
__ li(a2, Operand(prop->key()->AsLiteral()->value()));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic);
|
||||
CallStoreIC(NOT_CONTEXTUAL);
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
@ -2467,11 +2456,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
__ mov(a0, result_register());
|
||||
__ li(a2, Operand(var->name()));
|
||||
__ lw(a1, GlobalObjectOperand());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
|
||||
CallStoreIC(CONTEXTUAL);
|
||||
} else if (op == Token::INIT_CONST) {
|
||||
// Const initializers need a write barrier.
|
||||
ASSERT(!var->IsParameter()); // No const parameters.
|
||||
@ -2569,10 +2554,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
__ li(a2, Operand(prop->key()->AsLiteral()->value()));
|
||||
__ pop(a1);
|
||||
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(v0);
|
||||
@ -2595,7 +2577,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(v0);
|
||||
@ -2622,16 +2604,17 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::CallIC(Handle<Code> code,
|
||||
RelocInfo::Mode rmode,
|
||||
ContextualMode mode,
|
||||
TypeFeedbackId id) {
|
||||
ic_total_count_++;
|
||||
__ Call(code, rmode, id);
|
||||
ASSERT(mode != CONTEXTUAL || id.IsNone());
|
||||
__ Call(code, RelocInfo::CODE_TARGET, id);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> name,
|
||||
RelocInfo::Mode mode) {
|
||||
ContextualMode mode) {
|
||||
// Code common for calls using the IC.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -2646,7 +2629,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallFeedbackId());
|
||||
TypeFeedbackId ast_id = mode == CONTEXTUAL
|
||||
? TypeFeedbackId::None()
|
||||
: expr->CallFeedbackId();
|
||||
CallIC(ic, mode, ast_id);
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
@ -2679,7 +2665,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
|
||||
__ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
@ -2795,7 +2781,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Push global object as receiver for the call IC.
|
||||
__ lw(a0, GlobalObjectOperand());
|
||||
__ push(a0);
|
||||
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
||||
EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
Label slow, done;
|
||||
@ -2842,7 +2828,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
if (property->key()->IsPropertyName()) {
|
||||
EmitCallWithIC(expr,
|
||||
property->key()->AsLiteral()->value(),
|
||||
RelocInfo::CODE_TARGET);
|
||||
NOT_CONTEXTUAL);
|
||||
} else {
|
||||
EmitKeyedCallWithIC(expr, property->key());
|
||||
}
|
||||
@ -4213,7 +4199,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
if (expr->is_jsruntime()) {
|
||||
// Call the JS runtime function.
|
||||
__ li(a2, Operand(expr->name()));
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
ContextualMode mode = NOT_CONTEXTUAL;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallRuntimeFeedbackId());
|
||||
@ -4467,7 +4453,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
|
||||
BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);
|
||||
CallIC(stub.GetCode(isolate()),
|
||||
RelocInfo::CODE_TARGET,
|
||||
NOT_CONTEXTUAL,
|
||||
expr->CountBinOpFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ bind(&done);
|
||||
@ -4498,10 +4484,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ mov(a0, result_register()); // Value.
|
||||
__ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name.
|
||||
__ pop(a1); // Receiver.
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4518,7 +4501,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4541,10 +4524,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ lw(a0, GlobalObjectOperand());
|
||||
__ li(a2, Operand(proxy->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallIC(ic);
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
context()->Plug(v0);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
@ -4704,7 +4686,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||
@ -4738,7 +4720,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
||||
Split(eq, a0, Operand(a1), if_true, if_false, fall_through);
|
||||
} else {
|
||||
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||
}
|
||||
context()->Plug(if_true, if_false);
|
||||
|
@ -646,7 +646,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a2 : name
|
||||
// -- ra : return address
|
||||
@ -654,8 +654,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
|
||||
// Probe the stub cache.
|
||||
ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::HANDLER, MONOMORPHIC, kNoExtraICState,
|
||||
Code::HANDLER, MONOMORPHIC, extra_ic_state,
|
||||
Code::NORMAL, Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, a0, a2, a3, t0, t1, t2);
|
||||
|
@ -2815,10 +2815,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(v0));
|
||||
|
||||
__ li(a2, Operand(instr->name()));
|
||||
RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, mode, instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -2853,10 +2852,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(a0));
|
||||
|
||||
__ li(a2, Operand(instr->name()));
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -2953,7 +2952,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
// Name is always in a2.
|
||||
__ li(a2, Operand(instr->name()));
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3905,11 +3904,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(v0));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL);
|
||||
__ li(a2, Operand(instr->name()));
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -3934,11 +3932,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(v0));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL);
|
||||
__ li(a2, Operand(instr->name()));
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -4135,9 +4132,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
|
||||
// Name is always in a2.
|
||||
__ li(a2, Operand(instr->name()));
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -10617,8 +10617,7 @@ void Code::ClearInlineCaches(Code::Kind kind) {
|
||||
void Code::ClearInlineCaches(Code::Kind* kind) {
|
||||
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
|
||||
for (RelocIterator it(this, mask); !it.done(); it.next()) {
|
||||
RelocInfo* info = it.rinfo();
|
||||
Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
|
||||
@ -10843,6 +10842,17 @@ bool Code::CanDeoptAt(Address pc) {
|
||||
}
|
||||
|
||||
|
||||
bool Code::IsContextual() {
|
||||
ASSERT(is_inline_cache_stub());
|
||||
Kind kind = this->kind();
|
||||
if (kind == STORE_IC || kind == LOAD_IC || kind == CALL_IC) {
|
||||
ExtraICState extra_state = extra_ic_state();
|
||||
return IC::GetContextualMode(extra_state) == CONTEXTUAL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Identify kind of code.
|
||||
const char* Code::Kind2String(Kind kind) {
|
||||
switch (kind) {
|
||||
|
@ -5137,6 +5137,7 @@ class Code: public HeapObject {
|
||||
kind == BINARY_OP_IC;
|
||||
}
|
||||
|
||||
bool IsContextual(); // Only valid for IC stubs.
|
||||
inline StubType type(); // Only valid for monomorphic IC stubs.
|
||||
inline int arguments_count(); // Only valid for call IC stubs.
|
||||
|
||||
|
@ -147,10 +147,10 @@ Handle<Code> StubCache::ComputeMonomorphicIC(
|
||||
}
|
||||
|
||||
if (kind == Code::LOAD_IC) {
|
||||
LoadStubCompiler ic_compiler(isolate(), flag);
|
||||
LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
|
||||
ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
|
||||
} else if (kind == Code::KEYED_LOAD_IC) {
|
||||
KeyedLoadStubCompiler ic_compiler(isolate(), flag);
|
||||
KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
|
||||
ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
|
||||
} else if (kind == Code::STORE_IC) {
|
||||
StoreStubCompiler ic_compiler(isolate(), extra_ic_state);
|
||||
@ -419,12 +419,11 @@ static void FillCache(Isolate* isolate, Handle<Code> code) {
|
||||
|
||||
|
||||
Code* StubCache::FindCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
ContextualMode mode,
|
||||
Code::Kind kind) {
|
||||
ExtraICState extra_state =
|
||||
CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
|
||||
CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT
|
||||
? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||
CallICBase::Contextual::encode(mode);
|
||||
Code::Flags flags =
|
||||
Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
|
||||
UnseededNumberDictionary* dictionary =
|
||||
@ -438,13 +437,24 @@ Code* StubCache::FindCallInitialize(int argc,
|
||||
}
|
||||
|
||||
|
||||
Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) {
|
||||
Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
|
||||
UnseededNumberDictionary* dictionary =
|
||||
isolate()->heap()->non_monomorphic_cache();
|
||||
int entry = dictionary->FindEntry(isolate(), flags);
|
||||
ASSERT(entry != -1);
|
||||
Object* code = dictionary->ValueAt(entry);
|
||||
// This might be called during the marking phase of the collector
|
||||
// hence the unchecked cast.
|
||||
return reinterpret_cast<Code*>(code);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
ContextualMode mode,
|
||||
Code::Kind kind) {
|
||||
ExtraICState extra_state =
|
||||
CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
|
||||
CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT
|
||||
? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||
CallICBase::ComputeExtraICState(mode, DEFAULT_STRING_STUB);
|
||||
Code::Flags flags =
|
||||
Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
|
||||
Handle<UnseededNumberDictionary> cache =
|
||||
@ -459,14 +469,13 @@ Handle<Code> StubCache::ComputeCallInitialize(int argc,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
|
||||
Handle<Code> StubCache::ComputeCallInitialize(int argc, ContextualMode mode) {
|
||||
return ComputeCallInitialize(argc, mode, Code::CALL_IC);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
|
||||
return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
|
||||
Code::KEYED_CALL_IC);
|
||||
return ComputeCallInitialize(argc, NOT_CONTEXTUAL, Code::KEYED_CALL_IC);
|
||||
}
|
||||
|
||||
|
||||
@ -540,6 +549,57 @@ Handle<Code> StubCache::ComputeCallMegamorphic(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state,
|
||||
ExtraICState extra_state) {
|
||||
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state);
|
||||
Handle<UnseededNumberDictionary> cache =
|
||||
isolate_->factory()->non_monomorphic_cache();
|
||||
int entry = cache->FindEntry(isolate_, flags);
|
||||
if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
||||
|
||||
StubCompiler compiler(isolate_);
|
||||
Handle<Code> code;
|
||||
if (ic_state == UNINITIALIZED) {
|
||||
code = compiler.CompileLoadInitialize(flags);
|
||||
} else if (ic_state == PREMONOMORPHIC) {
|
||||
code = compiler.CompileLoadPreMonomorphic(flags);
|
||||
} else if (ic_state == MEGAMORPHIC) {
|
||||
code = compiler.CompileLoadMegamorphic(flags);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
FillCache(isolate_, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state,
|
||||
ExtraICState extra_state) {
|
||||
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state);
|
||||
Handle<UnseededNumberDictionary> cache =
|
||||
isolate_->factory()->non_monomorphic_cache();
|
||||
int entry = cache->FindEntry(isolate_, flags);
|
||||
if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
||||
|
||||
StubCompiler compiler(isolate_);
|
||||
Handle<Code> code;
|
||||
if (ic_state == UNINITIALIZED) {
|
||||
code = compiler.CompileStoreInitialize(flags);
|
||||
} else if (ic_state == PREMONOMORPHIC) {
|
||||
code = compiler.CompileStorePreMonomorphic(flags);
|
||||
} else if (ic_state == GENERIC) {
|
||||
code = compiler.CompileStoreGeneric(flags);
|
||||
} else if (ic_state == MEGAMORPHIC) {
|
||||
code = compiler.CompileStoreMegamorphic(flags);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
FillCache(isolate_, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeCallMiss(int argc,
|
||||
Code::Kind kind,
|
||||
ExtraICState extra_state) {
|
||||
@ -618,13 +678,12 @@ Handle<Code> StubCache::ComputePolymorphicIC(
|
||||
Code::StubType type = number_of_valid_types == 1 ? handler->type()
|
||||
: Code::NORMAL;
|
||||
if (kind == Code::LOAD_IC) {
|
||||
LoadStubCompiler ic_compiler(isolate_);
|
||||
LoadStubCompiler ic_compiler(isolate_, extra_ic_state);
|
||||
return ic_compiler.CompilePolymorphicIC(
|
||||
types, handlers, name, type, PROPERTY);
|
||||
} else {
|
||||
ASSERT(kind == Code::STORE_IC);
|
||||
StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_ic_state);
|
||||
StoreStubCompiler ic_compiler(isolate_, strict_mode);
|
||||
StoreStubCompiler ic_compiler(isolate_, extra_ic_state);
|
||||
return ic_compiler.CompilePolymorphicIC(
|
||||
types, handlers, name, type, PROPERTY);
|
||||
}
|
||||
@ -834,7 +893,9 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
|
||||
HandleScope scope(isolate);
|
||||
IC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
ASSERT(ic.IsLoadStub());
|
||||
if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value();
|
||||
if (!ic.IsContextual()) {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
// Throw a reference error.
|
||||
Handle<Name> name_handle(name);
|
||||
@ -1027,6 +1088,81 @@ Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) {
|
||||
LoadIC::GenerateInitialize(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) {
|
||||
LoadIC::GeneratePreMonomorphic(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) {
|
||||
ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
||||
ContextualMode mode = IC::GetContextualMode(extra_state);
|
||||
LoadIC::GenerateMegamorphic(masm(), mode);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) {
|
||||
StoreIC::GenerateInitialize(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileStorePreMonomorphic(Code::Flags flags) {
|
||||
StoreIC::GeneratePreMonomorphic(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileStoreGeneric(Code::Flags flags) {
|
||||
ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
||||
StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_state);
|
||||
StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) {
|
||||
ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
|
||||
StoreIC::GenerateMegamorphic(masm(), extra_state);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0));
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
|
||||
int argc = Code::ExtractArgumentsCountFromFlags(flags);
|
||||
KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
|
||||
|
@ -138,7 +138,7 @@ class StubCache {
|
||||
|
||||
// ---
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
|
||||
Handle<Code> ComputeCallInitialize(int argc, ContextualMode mode);
|
||||
|
||||
Handle<Code> ComputeKeyedCallInitialize(int argc);
|
||||
|
||||
@ -162,6 +162,12 @@ class StubCache {
|
||||
|
||||
// ---
|
||||
|
||||
Handle<Code> ComputeLoad(InlineCacheState ic_state, ExtraICState extra_state);
|
||||
Handle<Code> ComputeStore(InlineCacheState ic_state,
|
||||
ExtraICState extra_state);
|
||||
|
||||
// ---
|
||||
|
||||
Handle<Code> ComputeCompareNil(Handle<Map> receiver_map,
|
||||
CompareNilICStub& stub);
|
||||
|
||||
@ -179,7 +185,8 @@ class StubCache {
|
||||
ExtraICState extra_ic_state);
|
||||
|
||||
// Finds the Code object stored in the Heap::non_monomorphic_cache().
|
||||
Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
|
||||
Code* FindCallInitialize(int argc, ContextualMode mode, Code::Kind kind);
|
||||
Code* FindPreMonomorphicIC(Code::Kind kind, ExtraICState extra_ic_state);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
|
||||
@ -263,7 +270,7 @@ class StubCache {
|
||||
explicit StubCache(Isolate* isolate);
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
ContextualMode mode,
|
||||
Code::Kind kind);
|
||||
|
||||
// The stub cache has a primary and secondary level. The two levels have
|
||||
@ -378,6 +385,15 @@ class StubCompiler BASE_EMBEDDED {
|
||||
Handle<Code> CompileCallArguments(Code::Flags flags);
|
||||
Handle<Code> CompileCallMiss(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileLoadInitialize(Code::Flags flags);
|
||||
Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags);
|
||||
Handle<Code> CompileLoadMegamorphic(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileStoreInitialize(Code::Flags flags);
|
||||
Handle<Code> CompileStorePreMonomorphic(Code::Flags flags);
|
||||
Handle<Code> CompileStoreGeneric(Code::Flags flags);
|
||||
Handle<Code> CompileStoreMegamorphic(Code::Flags flags);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
Handle<Code> CompileCallDebugBreak(Code::Flags flags);
|
||||
Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
|
||||
@ -503,6 +519,9 @@ class StubCompiler BASE_EMBEDDED {
|
||||
Isolate* isolate() { return isolate_; }
|
||||
Heap* heap() { return isolate()->heap(); }
|
||||
Factory* factory() { return isolate()->factory(); }
|
||||
ContextualMode contextual_mode() {
|
||||
return IC::GetContextualMode(extra_state());
|
||||
}
|
||||
|
||||
static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
|
||||
|
||||
|
@ -630,7 +630,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
|
||||
CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
|
||||
__ testq(result_register(), result_register());
|
||||
// The stub returns nonzero for true.
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
@ -983,7 +983,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
Label skip;
|
||||
@ -1353,11 +1353,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
// load IC call.
|
||||
__ movq(rax, GlobalObjectOperand());
|
||||
__ Move(rcx, var->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? RelocInfo::CODE_TARGET
|
||||
: RelocInfo::CODE_TARGET_CONTEXT;
|
||||
CallIC(ic, mode);
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
CallLoadIC(mode);
|
||||
}
|
||||
|
||||
|
||||
@ -1437,8 +1436,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// object on the stack.
|
||||
__ Move(rcx, var->name());
|
||||
__ movq(rax, GlobalObjectOperand());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(rax);
|
||||
break;
|
||||
}
|
||||
@ -1652,10 +1650,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ Move(rcx, key->value());
|
||||
__ movq(rdx, Operand(rsp, 0));
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
} else {
|
||||
VisitForEffect(value);
|
||||
@ -2077,8 +2072,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_loop);
|
||||
__ push(rax); // save result
|
||||
__ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
|
||||
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(done_ic); // result.done in rax
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ testq(result_register(), result_register());
|
||||
@ -2087,8 +2081,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(rax); // result
|
||||
__ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
|
||||
Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(value_ic); // result.value in rax
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
|
||||
context()->DropAndPlug(2, rax); // drop iter and g
|
||||
break;
|
||||
}
|
||||
@ -2234,15 +2227,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ Move(rcx, key->value());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
@ -2264,7 +2256,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
__ bind(&stub_call);
|
||||
__ movq(rax, rcx);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ jmp(&done, Label::kNear);
|
||||
@ -2314,7 +2306,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
||||
__ pop(rdx);
|
||||
BinaryOpICStub stub(op, mode);
|
||||
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
|
||||
CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
|
||||
CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
|
||||
expr->BinaryOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
context()->Plug(rax);
|
||||
@ -2353,10 +2345,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
||||
__ movq(rdx, rax);
|
||||
__ pop(rax); // Restore value.
|
||||
__ Move(rcx, prop->key()->AsLiteral()->value());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic);
|
||||
CallStoreIC(NOT_CONTEXTUAL);
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
@ -2383,10 +2372,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
// Global var, const, or let.
|
||||
__ Move(rcx, var->name());
|
||||
__ movq(rdx, GlobalObjectOperand());
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
CallStoreIC(CONTEXTUAL);
|
||||
} else if (op == Token::INIT_CONST) {
|
||||
// Const initializers need a write barrier.
|
||||
ASSERT(!var->IsParameter()); // No const parameters.
|
||||
@ -2477,10 +2463,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
SetSourcePosition(expr->position());
|
||||
__ Move(rcx, prop->key()->AsLiteral()->value());
|
||||
__ pop(rdx);
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(rax);
|
||||
@ -2497,7 +2480,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
context()->Plug(rax);
|
||||
@ -2524,16 +2507,17 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::CallIC(Handle<Code> code,
|
||||
RelocInfo::Mode rmode,
|
||||
ContextualMode mode,
|
||||
TypeFeedbackId ast_id) {
|
||||
ic_total_count_++;
|
||||
__ call(code, rmode, ast_id);
|
||||
ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
|
||||
__ call(code, RelocInfo::CODE_TARGET, ast_id);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
Handle<Object> name,
|
||||
RelocInfo::Mode mode) {
|
||||
ContextualMode mode) {
|
||||
// Code common for calls using the IC.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -2548,7 +2532,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallFeedbackId());
|
||||
TypeFeedbackId ast_id = mode == CONTEXTUAL
|
||||
? TypeFeedbackId::None()
|
||||
: expr->CallFeedbackId();
|
||||
CallIC(ic, mode, ast_id);
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
@ -2581,7 +2568,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
|
||||
__ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
@ -2693,7 +2680,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Call to a global variable. Push global object as receiver for the
|
||||
// call IC lookup.
|
||||
__ push(GlobalObjectOperand());
|
||||
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
|
||||
EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
Label slow, done;
|
||||
@ -2737,7 +2724,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
if (property->key()->IsPropertyName()) {
|
||||
EmitCallWithIC(expr,
|
||||
property->key()->AsLiteral()->value(),
|
||||
RelocInfo::CODE_TARGET);
|
||||
NOT_CONTEXTUAL);
|
||||
} else {
|
||||
EmitKeyedCallWithIC(expr, property->key());
|
||||
}
|
||||
@ -4146,7 +4133,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
if (expr->is_jsruntime()) {
|
||||
// Call the JS runtime function using a call IC.
|
||||
__ Move(rcx, expr->name());
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
ContextualMode mode = NOT_CONTEXTUAL;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
|
||||
CallIC(ic, mode, expr->CallRuntimeFeedbackId());
|
||||
@ -4400,7 +4387,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ Move(rax, Smi::FromInt(1));
|
||||
BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
|
||||
CallIC(stub.GetCode(isolate()),
|
||||
RelocInfo::CODE_TARGET,
|
||||
NOT_CONTEXTUAL,
|
||||
expr->CountBinOpFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
__ bind(&done);
|
||||
@ -4432,10 +4419,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
case NAMED_PROPERTY: {
|
||||
__ Move(rcx, prop->key()->AsLiteral()->value());
|
||||
__ pop(rdx);
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->StoreIC_Initialize()
|
||||
: isolate()->builtins()->StoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4452,7 +4436,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
Handle<Code> ic = is_classic_mode()
|
||||
? isolate()->builtins()->KeyedStoreIC_Initialize()
|
||||
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
@ -4476,10 +4460,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ Move(rcx, proxy->name());
|
||||
__ movq(rax, GlobalObjectOperand());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallIC(ic);
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
context()->Plug(rax);
|
||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
||||
@ -4641,7 +4624,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
patch_site.EmitPatchInfo();
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
@ -4676,7 +4659,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else {
|
||||
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
|
||||
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
|
||||
CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
|
||||
__ testq(rax, rax);
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
}
|
||||
|
@ -1345,7 +1345,7 @@ void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
@ -1353,8 +1353,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
|
||||
// Probe the stub cache.
|
||||
ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::HANDLER, MONOMORPHIC, kNoExtraICState,
|
||||
Code::HANDLER, MONOMORPHIC, extra_ic_state,
|
||||
Code::NORMAL, Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, rax, rcx, rbx, rdx);
|
||||
|
@ -2708,10 +2708,9 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->name());
|
||||
RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
|
||||
RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, mode, instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -2747,10 +2746,10 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->name());
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -2857,7 +2856,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
@ -3801,11 +3800,10 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL);
|
||||
__ Move(rcx, instr->name());
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -3832,11 +3830,10 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(rsi));
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
int arity = instr->arity();
|
||||
RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
|
||||
Handle<Code> ic =
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
|
||||
isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL);
|
||||
__ Move(rcx, instr->name());
|
||||
CallCode(ic, mode, instr);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
||||
@ -4075,9 +4072,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->value()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->hydrogen()->name());
|
||||
Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
|
||||
? isolate()->builtins()->StoreIC_Initialize_Strict()
|
||||
: isolate()->builtins()->StoreIC_Initialize();
|
||||
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
|
||||
instr->strict_mode_flag(),
|
||||
NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
|
||||
|
@ -1040,13 +1040,13 @@ TEST(DebugStub) {
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f2(){x=1;}", "f2",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kStoreIC_DebugBreak));
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f3(){var a=x;}", "f3",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kLoadIC_DebugBreak));
|
||||
|
||||
@ -1091,19 +1091,19 @@ TEST(DebugStub) {
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f4_0(){x();}", "f4_0",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
*debug_break_0);
|
||||
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f4_1(){x(1);}", "f4_1",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
*debug_break_1);
|
||||
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f4_4(){x(1,2,3,4);}", "f4_4",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
*debug_break_4);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
#include "stub-cache.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "disasm.h"
|
||||
@ -254,7 +255,7 @@ TEST(DisasmIa320) {
|
||||
__ bind(&L2);
|
||||
__ call(Operand(ebx, ecx, times_4, 10000));
|
||||
__ nop();
|
||||
Handle<Code> ic(isolate->builtins()->builtin(Builtins::kLoadIC_Initialize));
|
||||
Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_CONTEXTUAL));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
__ nop();
|
||||
__ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
|
||||
|
@ -2839,8 +2839,7 @@ TEST(IncrementalMarkingClearsTypeFeedbackCells) {
|
||||
static Code* FindFirstIC(Code* code, Code::Kind kind) {
|
||||
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
|
||||
for (RelocIterator it(code, mask); !it.done(); it.next()) {
|
||||
RelocInfo* info = it.rinfo();
|
||||
Code* target = Code::GetCodeFromTargetAddress(info->target_address());
|
||||
@ -2852,7 +2851,7 @@ static Code* FindFirstIC(Code* code, Code::Kind kind) {
|
||||
}
|
||||
|
||||
|
||||
TEST(IncrementalMarkingPreservesMonomorhpicIC) {
|
||||
TEST(IncrementalMarkingPreservesMonomorphicIC) {
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
@ -2877,7 +2876,7 @@ TEST(IncrementalMarkingPreservesMonomorhpicIC) {
|
||||
}
|
||||
|
||||
|
||||
TEST(IncrementalMarkingClearsMonomorhpicIC) {
|
||||
TEST(IncrementalMarkingClearsMonomorphicIC) {
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
@ -2911,7 +2910,7 @@ TEST(IncrementalMarkingClearsMonomorhpicIC) {
|
||||
}
|
||||
|
||||
|
||||
TEST(IncrementalMarkingClearsPolymorhpicIC) {
|
||||
TEST(IncrementalMarkingClearsPolymorphicIC) {
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
@ -3060,7 +3059,7 @@ TEST(Regression144230) {
|
||||
HandleScope inner_scope(isolate);
|
||||
AlwaysAllocateScope always_allocate;
|
||||
SimulateFullSpace(heap->code_space());
|
||||
isolate->stub_cache()->ComputeCallInitialize(9, RelocInfo::CODE_TARGET);
|
||||
isolate->stub_cache()->ComputeCallInitialize(9, NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
// Second compile a CallIC and execute it once so that it gets patched to
|
||||
|
116
test/mjsunit/context-calls-maintained.js
Normal file
116
test/mjsunit/context-calls-maintained.js
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --expose-gc --allow-natives-syntax
|
||||
|
||||
function clear_all_ics() {
|
||||
%NotifyContextDisposed();
|
||||
gc();
|
||||
gc();
|
||||
gc();
|
||||
}
|
||||
|
||||
|
||||
// Test: verify that a monomorphic call retains the structural knowledge
|
||||
// of a global call, correctly throwing either ReferenceError or
|
||||
// TypeError on undefined depending on how the call is made.
|
||||
(function() {
|
||||
foo = function(arg) { return arg + 1; }
|
||||
|
||||
function f() { foo(1); }
|
||||
|
||||
// Drive to monomorphic
|
||||
f(); f(); f();
|
||||
|
||||
delete foo;
|
||||
assertThrows(function() { f(); }, ReferenceError);
|
||||
foo = function(arg) { return arg * 2; }
|
||||
assertDoesNotThrow(function() { f(); });
|
||||
f(); f(); f();
|
||||
delete foo;
|
||||
assertThrows(function() { f(); }, ReferenceError);
|
||||
clear_all_ics();
|
||||
foo = function(arg) { return arg * 3; }
|
||||
f();
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f();
|
||||
delete foo;
|
||||
assertThrows(function() { f(); }, ReferenceError);
|
||||
|
||||
foo = function(arg) { return arg * 3; }
|
||||
function g() { this.foo(1); }
|
||||
g(); g(); g();
|
||||
delete foo;
|
||||
assertThrows(function() { g(); }, TypeError);
|
||||
foo = function(arg) { return arg * 3; }
|
||||
g();
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
g();
|
||||
delete foo;
|
||||
assertThrows(function() { g(); }, TypeError);
|
||||
})();
|
||||
|
||||
|
||||
// Test: verify that a load with IC does the right thing.
|
||||
(function() {
|
||||
var foo = function() { return a; }
|
||||
a = 3;
|
||||
foo(); foo(); foo();
|
||||
delete a;
|
||||
assertThrows(function() { foo(); }, ReferenceError);
|
||||
a = "hi";
|
||||
foo();
|
||||
clear_all_ics();
|
||||
foo();
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo();
|
||||
delete a;
|
||||
assertThrows(function() { foo(); }, ReferenceError);
|
||||
foo = function() { return this.a; }
|
||||
assertDoesNotThrow(function() { foo(); });
|
||||
})();
|
||||
|
||||
|
||||
// Test: verify that a store with IC does the right thing.
|
||||
// If store is contextual and strict mode is set, throw a ReferenceError
|
||||
// if the variable isn't found.
|
||||
(function() {
|
||||
var foo = function() { a = 3; }
|
||||
var bar = function() { "use strict"; a = 3; }
|
||||
foo(); foo(); foo();
|
||||
delete a;
|
||||
assertThrows(function() { bar(); }, ReferenceError);
|
||||
a = 6;
|
||||
foo(); foo(); foo();
|
||||
bar(); bar();
|
||||
clear_all_ics();
|
||||
bar();
|
||||
%OptimizeFunctionOnNextCall(bar);
|
||||
bar();
|
||||
delete a;
|
||||
assertThrows(function() { bar(); }, ReferenceError);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user