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:
mvstanton@chromium.org 2014-01-07 14:14:34 +00:00
parent 22eff6f87a
commit e3e7daf01c
31 changed files with 694 additions and 542 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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) \
\

View File

@ -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> {};

View File

@ -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();

View File

@ -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

View File

@ -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_; }

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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
View File

@ -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();

View File

@ -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") \

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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) {

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View 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);
})();