Handlify the stub cache lookup and patching for CallIC and KeyedCallIC.
R=ulan@chromium.org,vegorov@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/8357010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9729 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a5da9320d2
commit
e3792a6830
@ -1101,24 +1101,16 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
|
||||
// You can't call a function without a valid frame.
|
||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||
|
||||
ASSERT(function->is_compiled());
|
||||
|
||||
// Get the function and setup the context.
|
||||
mov(r1, Operand(Handle<JSFunction>(function)));
|
||||
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
|
||||
|
||||
// Invoke the cached code.
|
||||
Handle<Code> code(function->code());
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
if (V8::UseCrankshaft()) {
|
||||
// TODO(kasperl): For now, we always call indirectly through the
|
||||
// code field in the function to allow recompilation to take effect
|
||||
// without changing any of the call sites.
|
||||
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
||||
InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind);
|
||||
} else {
|
||||
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
||||
InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1480,9 +1480,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
||||
|
||||
MaybeObject* CallStubCompiler::GenerateMissBranch() {
|
||||
MaybeObject* maybe_obj =
|
||||
isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_ic_state_);
|
||||
isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_state_);
|
||||
Object* obj;
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
|
||||
@ -1513,7 +1513,7 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
|
||||
Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
|
||||
GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
|
||||
|
||||
GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
|
||||
GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
@ -1831,7 +1831,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -1917,7 +1917,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -2474,7 +2474,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind);
|
||||
@ -2510,7 +2510,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
// Get the receiver from the stack.
|
||||
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
|
||||
|
||||
CallInterceptorCompiler compiler(this, arguments(), r2, extra_ic_state_);
|
||||
CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_);
|
||||
MaybeObject* result = compiler.Compile(masm(),
|
||||
object,
|
||||
holder,
|
||||
@ -2530,7 +2530,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
// Restore receiver.
|
||||
__ ldr(r0, MemOperand(sp, argc * kPointerSize));
|
||||
|
||||
GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
|
||||
GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
@ -2585,23 +2585,17 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
||||
// Jump to the cached code (tail call).
|
||||
Counters* counters = masm()->isolate()->counters();
|
||||
__ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
|
||||
ASSERT(function->is_compiled());
|
||||
Handle<Code> code(function->code());
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
if (V8::UseCrankshaft()) {
|
||||
// TODO(kasperl): For now, we always call indirectly through the
|
||||
// code field in the function to allow recompilation to take effect
|
||||
// without changing any of the call sites.
|
||||
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
||||
__ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
} else {
|
||||
__ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET,
|
||||
JUMP_FUNCTION, call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
||||
__ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
|
10
src/debug.cc
10
src/debug.cc
@ -87,19 +87,13 @@ static void PrintLn(v8::Local<v8::Value> value) {
|
||||
|
||||
static Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate,
|
||||
isolate->stub_cache()->ComputeCallDebugBreak(argc, kind),
|
||||
Code);
|
||||
return isolate->stub_cache()->ComputeCallDebugBreak(argc, kind);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate,
|
||||
isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind),
|
||||
Code);
|
||||
return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2087,23 +2087,16 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
|
||||
// You can't call a function without a valid frame.
|
||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||
|
||||
ASSERT(function->is_compiled());
|
||||
// Get the function and setup the context.
|
||||
mov(edi, Immediate(Handle<JSFunction>(function)));
|
||||
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
|
||||
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
if (V8::UseCrankshaft()) {
|
||||
// TODO(kasperl): For now, we always call indirectly through the
|
||||
// code field in the function to allow recompilation to take effect
|
||||
// without changing any of the call sites.
|
||||
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
|
||||
expected, actual, flag, call_wrapper, call_kind);
|
||||
} else {
|
||||
Handle<Code> code(function->code());
|
||||
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET,
|
||||
flag, call_wrapper, call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
|
||||
expected, actual, flag, call_wrapper, call_kind);
|
||||
}
|
||||
|
||||
|
||||
|
@ -486,11 +486,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
CallInterceptorCompiler(StubCompiler* stub_compiler,
|
||||
const ParameterCount& arguments,
|
||||
Register name,
|
||||
Code::ExtraICState extra_ic_state)
|
||||
Code::ExtraICState extra_state)
|
||||
: stub_compiler_(stub_compiler),
|
||||
arguments_(arguments),
|
||||
name_(name),
|
||||
extra_ic_state_(extra_ic_state) {}
|
||||
extra_state_(extra_state) {}
|
||||
|
||||
MaybeObject* Compile(MacroAssembler* masm,
|
||||
JSObject* object,
|
||||
@ -614,7 +614,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
||||
if (result->IsFailure()) return result;
|
||||
} else {
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(optimization.constant_function(), arguments_,
|
||||
@ -700,7 +700,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
StubCompiler* stub_compiler_;
|
||||
const ParameterCount& arguments_;
|
||||
Register name_;
|
||||
Code::ExtraICState extra_ic_state_;
|
||||
Code::ExtraICState extra_state_;
|
||||
};
|
||||
|
||||
|
||||
@ -1337,9 +1337,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
||||
|
||||
MaybeObject* CallStubCompiler::GenerateMissBranch() {
|
||||
MaybeObject* maybe_obj =
|
||||
isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_ic_state_);
|
||||
isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_state_);
|
||||
Object* obj;
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
__ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
|
||||
@ -1389,7 +1389,7 @@ MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField(
|
||||
}
|
||||
|
||||
// Invoke the function.
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
|
||||
@ -1700,7 +1700,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -1786,7 +1786,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -1908,7 +1908,7 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
// Tail call the full function. We do not have to patch the receiver
|
||||
// because the function makes no use of it.
|
||||
__ bind(&slow);
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
||||
@ -2339,7 +2339,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
||||
@ -2378,7 +2378,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
// Get the receiver from the stack.
|
||||
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
||||
|
||||
CallInterceptorCompiler compiler(this, arguments(), ecx, extra_ic_state_);
|
||||
CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_);
|
||||
MaybeObject* result = compiler.Compile(masm(),
|
||||
object,
|
||||
holder,
|
||||
@ -2408,7 +2408,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
|
||||
// Invoke the function.
|
||||
__ mov(edi, eax);
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
|
||||
@ -2470,24 +2470,16 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(
|
||||
// Jump to the cached code (tail call).
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->call_global_inline(), 1);
|
||||
ASSERT(function->is_compiled());
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
if (V8::UseCrankshaft()) {
|
||||
// TODO(kasperl): For now, we always call indirectly through the
|
||||
// code field in the function to allow recompilation to take effect
|
||||
// without changing any of the call sites.
|
||||
__ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
|
||||
expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
} else {
|
||||
Handle<Code> code(function->code());
|
||||
__ InvokeCode(code, expected, arguments(),
|
||||
RelocInfo::CODE_TARGET, JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
__ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
|
||||
expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
|
217
src/ic.cc
217
src/ic.cc
@ -100,7 +100,11 @@ void IC::TraceIC(const char* type,
|
||||
PrintF("]\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
#define TRACE_IC(type, name, old_state, new_target) \
|
||||
ASSERT((TraceIC(type, name, old_state, new_target), true))
|
||||
|
||||
|
||||
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
|
||||
@ -578,89 +582,57 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* CallICBase::ComputeMonomorphicStub(
|
||||
LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name) {
|
||||
Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name) {
|
||||
int argc = target()->arguments_count();
|
||||
MaybeObject* maybe_code = NULL;
|
||||
Handle<JSObject> holder(lookup->holder());
|
||||
switch (lookup->type()) {
|
||||
case FIELD: {
|
||||
int index = lookup->GetFieldIndex();
|
||||
maybe_code = isolate()->stub_cache()->ComputeCallField(argc,
|
||||
kind_,
|
||||
extra_ic_state,
|
||||
*name,
|
||||
*object,
|
||||
lookup->holder(),
|
||||
index);
|
||||
break;
|
||||
return isolate()->stub_cache()->ComputeCallField(
|
||||
argc, kind_, extra_state, name, object, holder, index);
|
||||
}
|
||||
case CONSTANT_FUNCTION: {
|
||||
// Get the constant function and compute the code stub for this
|
||||
// call; used for rewriting to monomorphic state and making sure
|
||||
// that the code stub is in the stub cache.
|
||||
JSFunction* function = lookup->GetConstantFunction();
|
||||
maybe_code =
|
||||
isolate()->stub_cache()->ComputeCallConstant(argc,
|
||||
kind_,
|
||||
extra_ic_state,
|
||||
*name,
|
||||
*object,
|
||||
lookup->holder(),
|
||||
function);
|
||||
break;
|
||||
Handle<JSFunction> function(lookup->GetConstantFunction());
|
||||
return isolate()->stub_cache()->ComputeCallConstant(
|
||||
argc, kind_, extra_state, name, object, holder, function);
|
||||
}
|
||||
case NORMAL: {
|
||||
if (!object->IsJSObject()) return NULL;
|
||||
// If we return a null handle, the IC will not be patched.
|
||||
if (!object->IsJSObject()) return Handle<Code>::null();
|
||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||
|
||||
if (lookup->holder()->IsGlobalObject()) {
|
||||
GlobalObject* global = GlobalObject::cast(lookup->holder());
|
||||
JSGlobalPropertyCell* cell =
|
||||
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
|
||||
if (!cell->value()->IsJSFunction()) return NULL;
|
||||
JSFunction* function = JSFunction::cast(cell->value());
|
||||
maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc,
|
||||
kind_,
|
||||
extra_ic_state,
|
||||
*name,
|
||||
*receiver,
|
||||
global,
|
||||
cell,
|
||||
function);
|
||||
if (holder->IsGlobalObject()) {
|
||||
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
|
||||
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
|
||||
if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
|
||||
Handle<JSFunction> function(JSFunction::cast(cell->value()));
|
||||
return isolate()->stub_cache()->ComputeCallGlobal(
|
||||
argc, kind_, extra_state, name, receiver, global, cell, function);
|
||||
} else {
|
||||
// There is only one shared stub for calling normalized
|
||||
// properties. It does not traverse the prototype chain, so the
|
||||
// property must be found in the receiver for the stub to be
|
||||
// applicable.
|
||||
if (lookup->holder() != *receiver) return NULL;
|
||||
maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc,
|
||||
kind_,
|
||||
extra_ic_state,
|
||||
*name,
|
||||
*receiver);
|
||||
if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
|
||||
return isolate()->stub_cache()->ComputeCallNormal(
|
||||
argc, kind_, extra_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INTERCEPTOR: {
|
||||
ASSERT(HasInterceptorGetter(lookup->holder()));
|
||||
maybe_code = isolate()->stub_cache()->ComputeCallInterceptor(
|
||||
argc,
|
||||
kind_,
|
||||
extra_ic_state,
|
||||
*name,
|
||||
*object,
|
||||
lookup->holder());
|
||||
break;
|
||||
}
|
||||
case INTERCEPTOR:
|
||||
ASSERT(HasInterceptorGetter(*holder));
|
||||
return isolate()->stub_cache()->ComputeCallInterceptor(
|
||||
argc, kind_, extra_state, name, object, holder);
|
||||
default:
|
||||
maybe_code = NULL;
|
||||
break;
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
return maybe_code;
|
||||
}
|
||||
|
||||
|
||||
@ -682,75 +654,57 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
|
||||
|
||||
// Compute the number of arguments.
|
||||
int argc = target()->arguments_count();
|
||||
MaybeObject* maybe_code = NULL;
|
||||
bool had_proto_failure = false;
|
||||
Handle<Code> code;
|
||||
if (state == UNINITIALIZED) {
|
||||
// This is the first time we execute this inline cache.
|
||||
// Set the target to the pre monomorphic stub to delay
|
||||
// setting the monomorphic state.
|
||||
maybe_code =
|
||||
isolate()->stub_cache()->ComputeCallPreMonomorphic(argc,
|
||||
kind_,
|
||||
extra_ic_state);
|
||||
code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
|
||||
argc, kind_, extra_ic_state);
|
||||
} else if (state == MONOMORPHIC) {
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
|
||||
maybe_code = ComputeMonomorphicStub(lookup,
|
||||
state,
|
||||
extra_ic_state,
|
||||
object,
|
||||
name);
|
||||
code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
|
||||
object, name);
|
||||
} else if (kind_ == Code::CALL_IC &&
|
||||
TryRemoveInvalidPrototypeDependentStub(target(),
|
||||
*object,
|
||||
*name)) {
|
||||
had_proto_failure = true;
|
||||
maybe_code = ComputeMonomorphicStub(lookup,
|
||||
state,
|
||||
extra_ic_state,
|
||||
object,
|
||||
name);
|
||||
code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
|
||||
object, name);
|
||||
} else {
|
||||
maybe_code =
|
||||
isolate()->stub_cache()->ComputeCallMegamorphic(argc,
|
||||
kind_,
|
||||
extra_ic_state);
|
||||
code = isolate()->stub_cache()->ComputeCallMegamorphic(
|
||||
argc, kind_, extra_ic_state);
|
||||
}
|
||||
} else {
|
||||
maybe_code = ComputeMonomorphicStub(lookup,
|
||||
state,
|
||||
extra_ic_state,
|
||||
object,
|
||||
name);
|
||||
code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
|
||||
object, name);
|
||||
}
|
||||
|
||||
// If we're unable to compute the stub (not enough memory left), we
|
||||
// simply avoid updating the caches.
|
||||
Object* code;
|
||||
if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
|
||||
// If there's no appropriate stub we simply avoid updating the caches.
|
||||
if (code.is_null()) return;
|
||||
|
||||
// Patch the call site depending on the state of the cache.
|
||||
if (state == UNINITIALIZED ||
|
||||
state == PREMONOMORPHIC ||
|
||||
state == MONOMORPHIC ||
|
||||
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
|
||||
set_target(Code::cast(code));
|
||||
set_target(*code);
|
||||
} else if (state == MEGAMORPHIC) {
|
||||
// Cache code holding map should be consistent with
|
||||
// GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
|
||||
Map* map = JSObject::cast(object->IsJSObject() ? *object :
|
||||
object->GetPrototype())->map();
|
||||
|
||||
Handle<JSObject> cache_object = object->IsJSObject()
|
||||
? Handle<JSObject>::cast(object)
|
||||
: Handle<JSObject>(JSObject::cast(object->GetPrototype()));
|
||||
// Update the stub cache.
|
||||
isolate()->stub_cache()->Set(*name, map, Code::cast(code));
|
||||
isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
|
||||
}
|
||||
|
||||
USE(had_proto_failure);
|
||||
#ifdef DEBUG
|
||||
if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
|
||||
TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
|
||||
name, state, target());
|
||||
#endif
|
||||
TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
|
||||
name, state, target());
|
||||
}
|
||||
|
||||
|
||||
@ -774,25 +728,15 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
|
||||
isolate()->factory()->non_strict_arguments_elements_map();
|
||||
if (object->IsJSObject() &&
|
||||
Handle<JSObject>::cast(object)->elements()->map() == *map) {
|
||||
MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments(
|
||||
Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments(
|
||||
argc, Code::KEYED_CALL_IC);
|
||||
Code* code = NULL;
|
||||
if (maybe_code->To(&code)) {
|
||||
set_target(code);
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedCallIC", key, state, target());
|
||||
#endif
|
||||
}
|
||||
set_target(*code);
|
||||
TRACE_IC("KeyedCallIC", key, state, target());
|
||||
} else if (!object->IsAccessCheckNeeded()) {
|
||||
MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
|
||||
Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic(
|
||||
argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
|
||||
Code* code;
|
||||
if (maybe_code->To(&code)) {
|
||||
set_target(code);
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedCallIC", key, state, target());
|
||||
#endif
|
||||
}
|
||||
set_target(*code);
|
||||
TRACE_IC("KeyedCallIC", key, state, target());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1023,9 +967,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
||||
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("LoadIC", name, state, target());
|
||||
#endif
|
||||
TRACE_IC("LoadIC", name, state, target());
|
||||
}
|
||||
|
||||
|
||||
@ -1096,9 +1038,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
string);
|
||||
ASSERT(!code.is_null());
|
||||
set_target(*code);
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedLoadIC", name, state, target());
|
||||
#endif // DEBUG
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
return Smi::FromInt(string->length());
|
||||
}
|
||||
|
||||
@ -1110,9 +1050,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
|
||||
ASSERT(!code.is_null());
|
||||
set_target(*code);
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedLoadIC", name, state, target());
|
||||
#endif // DEBUG
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
return array->length();
|
||||
}
|
||||
|
||||
@ -1126,9 +1064,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
name, function);
|
||||
ASSERT(!code.is_null());
|
||||
set_target(*code);
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedLoadIC", name, state, target());
|
||||
#endif // DEBUG
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
return Accessors::FunctionGetPrototype(*object, 0);
|
||||
}
|
||||
}
|
||||
@ -1198,9 +1134,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
if (!stub.is_null()) set_target(*stub);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedLoadIC", key, state, target());
|
||||
#endif // DEBUG
|
||||
TRACE_IC("KeyedLoadIC", key, state, target());
|
||||
|
||||
// Get the property.
|
||||
return Runtime::GetObjectProperty(isolate(), object, key);
|
||||
@ -1273,9 +1207,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
|
||||
set_target(*megamorphic_stub());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedLoadIC", name, state, target());
|
||||
#endif
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
}
|
||||
|
||||
|
||||
@ -1390,9 +1322,7 @@ MaybeObject* StoreIC::Store(State state,
|
||||
: global_proxy_stub();
|
||||
if (target() != *stub) {
|
||||
set_target(*stub);
|
||||
#ifdef DEBUG
|
||||
TraceIC("StoreIC", name, state, target());
|
||||
#endif
|
||||
TRACE_IC("StoreIC", name, state, target());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1486,9 +1416,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("StoreIC", name, state, target());
|
||||
#endif
|
||||
TRACE_IC("StoreIC", name, state, target());
|
||||
}
|
||||
|
||||
|
||||
@ -1789,9 +1717,7 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
||||
if (!stub.is_null()) set_target(*stub);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedStoreIC", key, state, target());
|
||||
#endif
|
||||
TRACE_IC("KeyedStoreIC", key, state, target());
|
||||
|
||||
// Set the property.
|
||||
return Runtime::SetObjectProperty(
|
||||
@ -1863,12 +1789,13 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
: *megamorphic_stub());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TraceIC("KeyedStoreIC", name, state, target());
|
||||
#endif
|
||||
TRACE_IC("KeyedStoreIC", name, state, target());
|
||||
}
|
||||
|
||||
|
||||
#undef TRACE_IC
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Static IC stub generators.
|
||||
//
|
||||
|
12
src/ic.h
12
src/ic.h
@ -216,12 +216,12 @@ class CallICBase: public IC {
|
||||
Handle<Object> object,
|
||||
Code::ExtraICState* extra_ic_state);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
|
||||
LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name);
|
||||
// Compute a monomorphic stub if possible, otherwise return a null handle.
|
||||
Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name);
|
||||
|
||||
// Update the inline cache and the global stub cache based on the lookup
|
||||
// result.
|
||||
|
@ -3246,10 +3246,10 @@ void NormalizedMapCache::Clear() {
|
||||
}
|
||||
|
||||
|
||||
void JSObject::UpdateMapCodeCache(Isolate* isolate,
|
||||
Handle<JSObject> object,
|
||||
void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
|
||||
Handle<String> name,
|
||||
Handle<Code> code) {
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
CALL_HEAP_FUNCTION_VOID(isolate,
|
||||
object->UpdateMapCodeCache(*name, *code));
|
||||
}
|
||||
|
@ -1850,8 +1850,7 @@ class JSObject: public JSReceiver {
|
||||
// dictionary. Returns the backing after conversion.
|
||||
MUST_USE_RESULT MaybeObject* NormalizeElements();
|
||||
|
||||
static void UpdateMapCodeCache(Isolate* isolate,
|
||||
Handle<JSObject> object,
|
||||
static void UpdateMapCodeCache(Handle<JSObject> object,
|
||||
Handle<String> name,
|
||||
Handle<Code> code);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
227
src/stub-cache.h
227
src/stub-cache.h
@ -175,90 +175,73 @@ class StubCache {
|
||||
|
||||
// ---
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallField(
|
||||
int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
String* name,
|
||||
Object* object,
|
||||
JSObject* holder,
|
||||
int index);
|
||||
Handle<Code> ComputeCallField(int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<String> name,
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
int index);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallConstant(
|
||||
int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
String* name,
|
||||
Object* object,
|
||||
JSObject* holder,
|
||||
JSFunction* function);
|
||||
Handle<Code> ComputeCallConstant(int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<String> name,
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> function);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallNormal(
|
||||
int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
String* name,
|
||||
JSObject* receiver);
|
||||
Handle<Code> ComputeCallInterceptor(int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<String> name,
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallInterceptor(
|
||||
int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
String* name,
|
||||
Object* object,
|
||||
JSObject* holder);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallGlobal(
|
||||
int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
String* name,
|
||||
JSObject* receiver,
|
||||
GlobalObject* holder,
|
||||
JSGlobalPropertyCell* cell,
|
||||
JSFunction* function);
|
||||
Handle<Code> ComputeCallGlobal(int argc,
|
||||
Code::Kind,
|
||||
Code::ExtraICState extra_state,
|
||||
Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<GlobalObject> holder,
|
||||
Handle<JSGlobalPropertyCell> cell,
|
||||
Handle<JSFunction> function);
|
||||
|
||||
// ---
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
Code::Kind kind);
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc,
|
||||
RelocInfo::Mode mode);
|
||||
Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
|
||||
|
||||
Handle<Code> ComputeKeyedCallInitialize(int argc);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallPreMonomorphic(
|
||||
int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState extra_ic_state);
|
||||
Handle<Code> ComputeCallPreMonomorphic(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState extra_state);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
Handle<Code> ComputeCallNormal(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallArguments(int argc,
|
||||
Code::Kind kind);
|
||||
Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallMegamorphic(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
Handle<Code> ComputeCallMegamorphic(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallMiss(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
Handle<Code> ComputeCallMiss(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* TryComputeCallMiss(int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState state);
|
||||
|
||||
// Finds the Code object stored in the Heap::non_monomorphic_cache().
|
||||
MUST_USE_RESULT Code* FindCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
Code::Kind kind);
|
||||
Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallDebugBreak(int argc, Code::Kind kind);
|
||||
Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallDebugPrepareStepIn(int argc,
|
||||
Code::Kind kind);
|
||||
Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
|
||||
#endif
|
||||
|
||||
// Update cache for entry hash(name, map).
|
||||
@ -317,12 +300,9 @@ class StubCache {
|
||||
private:
|
||||
explicit StubCache(Isolate* isolate);
|
||||
|
||||
friend class Isolate;
|
||||
friend class SCTableReference;
|
||||
static const int kPrimaryTableSize = 2048;
|
||||
static const int kSecondaryTableSize = 512;
|
||||
Entry primary_[kPrimaryTableSize];
|
||||
Entry secondary_[kSecondaryTableSize];
|
||||
Handle<Code> ComputeCallInitialize(int argc,
|
||||
RelocInfo::Mode mode,
|
||||
Code::Kind kind);
|
||||
|
||||
// Computes the hashed offsets for primary and secondary caches.
|
||||
static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
|
||||
@ -367,8 +347,16 @@ class StubCache {
|
||||
reinterpret_cast<Address>(table) + (offset << shift_amount));
|
||||
}
|
||||
|
||||
static const int kPrimaryTableSize = 2048;
|
||||
static const int kSecondaryTableSize = 512;
|
||||
|
||||
Entry primary_[kPrimaryTableSize];
|
||||
Entry secondary_[kSecondaryTableSize];
|
||||
Isolate* isolate_;
|
||||
|
||||
friend class Isolate;
|
||||
friend class SCTableReference;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StubCache);
|
||||
};
|
||||
|
||||
@ -396,15 +384,31 @@ class StubCompiler BASE_EMBEDDED {
|
||||
explicit StubCompiler(Isolate* isolate)
|
||||
: isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallArguments(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
|
||||
Handle<Code> CompileCallInitialize(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallInitialize(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallPreMonomorphic(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallNormal(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallNormal(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallMegamorphic(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallMegamorphic(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallArguments(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallArguments(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallMiss(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallMiss(Code::Flags flags);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
|
||||
Handle<Code> CompileCallDebugBreak(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallDebugBreak(Code::Flags flags);
|
||||
|
||||
Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
|
||||
MUST_USE_RESULT MaybeObject* TryCompileCallDebugPrepareStepIn(
|
||||
Code::Flags flags);
|
||||
#endif
|
||||
|
||||
// Static functions for generating parts of stubs.
|
||||
@ -811,33 +815,50 @@ class CallStubCompiler: public StubCompiler {
|
||||
CallStubCompiler(Isolate* isolate,
|
||||
int argc,
|
||||
Code::Kind kind,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
Code::ExtraICState extra_state,
|
||||
InlineCacheHolderFlag cache_holder);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallField(
|
||||
JSObject* object,
|
||||
JSObject* holder,
|
||||
int index,
|
||||
String* name);
|
||||
Handle<Code> CompileCallField(Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
int index,
|
||||
Handle<String> name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallConstant(
|
||||
Object* object,
|
||||
JSObject* holder,
|
||||
JSFunction* function,
|
||||
String* name,
|
||||
CheckType check);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
|
||||
JSObject* holder,
|
||||
int index,
|
||||
String* name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallInterceptor(
|
||||
JSObject* object,
|
||||
JSObject* holder,
|
||||
String* name);
|
||||
Handle<Code> CompileCallConstant(Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
CheckType check);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallGlobal(
|
||||
JSObject* object,
|
||||
GlobalObject* holder,
|
||||
JSGlobalPropertyCell* cell,
|
||||
JSFunction* function,
|
||||
String* name);
|
||||
MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
|
||||
JSObject* holder,
|
||||
JSFunction* function,
|
||||
String* name,
|
||||
CheckType check);
|
||||
|
||||
Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<String> name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
|
||||
JSObject* holder,
|
||||
String* name);
|
||||
|
||||
Handle<Code> CompileCallGlobal(Handle<JSObject> object,
|
||||
Handle<GlobalObject> holder,
|
||||
Handle<JSGlobalPropertyCell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
|
||||
GlobalObject* holder,
|
||||
JSGlobalPropertyCell* cell,
|
||||
JSFunction* function,
|
||||
String* name);
|
||||
|
||||
static bool HasCustomCallGenerator(JSFunction* function);
|
||||
|
||||
@ -870,7 +891,7 @@ class CallStubCompiler: public StubCompiler {
|
||||
|
||||
const ParameterCount arguments_;
|
||||
const Code::Kind kind_;
|
||||
const Code::ExtraICState extra_ic_state_;
|
||||
const Code::ExtraICState extra_state_;
|
||||
const InlineCacheHolderFlag cache_holder_;
|
||||
|
||||
const ParameterCount& arguments() { return arguments_; }
|
||||
|
@ -3120,29 +3120,16 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
|
||||
// You can't call a function without a valid frame.
|
||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||
|
||||
ASSERT(function->is_compiled());
|
||||
// Get the function and setup the context.
|
||||
Move(rdi, Handle<JSFunction>(function));
|
||||
movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
||||
|
||||
if (V8::UseCrankshaft()) {
|
||||
// Since Crankshaft can recompile a function, we need to load
|
||||
// the Code object every time we call the function.
|
||||
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
|
||||
} else {
|
||||
// Invoke the cached code.
|
||||
Handle<Code> code(function->code());
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
InvokeCode(code,
|
||||
expected,
|
||||
actual,
|
||||
RelocInfo::CODE_TARGET,
|
||||
flag,
|
||||
call_wrapper,
|
||||
call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1307,9 +1307,9 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
||||
|
||||
MaybeObject* CallStubCompiler::GenerateMissBranch() {
|
||||
MaybeObject* maybe_obj =
|
||||
isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_ic_state_);
|
||||
isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_state_);
|
||||
Object* obj;
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
|
||||
@ -1360,7 +1360,7 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
|
||||
}
|
||||
|
||||
// Invoke the function.
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
|
||||
@ -1669,7 +1669,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -1753,7 +1753,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_ic_state_) ==
|
||||
(CallICBase::StringStubState::decode(extra_state_) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
@ -1871,7 +1871,7 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
// Tail call the full function. We do not have to patch the receiver
|
||||
// because the function makes no use of it.
|
||||
__ bind(&slow);
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
||||
@ -1988,7 +1988,7 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
||||
// Tail call the full function. We do not have to patch the receiver
|
||||
// because the function makes no use of it.
|
||||
__ bind(&slow);
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
||||
@ -2186,7 +2186,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
||||
@ -2227,7 +2227,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
// Get the receiver from the stack.
|
||||
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
|
||||
|
||||
CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_);
|
||||
CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_);
|
||||
MaybeObject* result = compiler.Compile(masm(),
|
||||
object,
|
||||
holder,
|
||||
@ -2257,7 +2257,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
|
||||
// Invoke the function.
|
||||
__ movq(rdi, rax);
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
|
||||
@ -2320,24 +2320,17 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
||||
// Jump to the cached code (tail call).
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->call_global_inline(), 1);
|
||||
ASSERT(function->is_compiled());
|
||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
||||
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
||||
? CALL_AS_FUNCTION
|
||||
: CALL_AS_METHOD;
|
||||
if (V8::UseCrankshaft()) {
|
||||
// TODO(kasperl): For now, we always call indirectly through the
|
||||
// code field in the function to allow recompilation to take effect
|
||||
// without changing any of the call sites.
|
||||
__ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
||||
__ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
} else {
|
||||
Handle<Code> code(function->code());
|
||||
__ InvokeCode(code, expected, arguments(),
|
||||
RelocInfo::CODE_TARGET, JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
}
|
||||
// We call indirectly through the code field in the function to
|
||||
// allow recompilation to take effect without changing any of the
|
||||
// call sites.
|
||||
__ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
||||
__ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
|
||||
NullCallWrapper(), call_kind);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
__ IncrementCounter(counters->call_global_inline_miss(), 1);
|
||||
|
@ -409,11 +409,8 @@ Handle<FixedArray> GetDebuggedFunctions() {
|
||||
|
||||
|
||||
static Handle<Code> ComputeCallDebugBreak(int argc) {
|
||||
CALL_HEAP_FUNCTION(
|
||||
v8::internal::Isolate::Current(),
|
||||
v8::internal::Isolate::Current()->stub_cache()->ComputeCallDebugBreak(
|
||||
argc, Code::CALL_IC),
|
||||
Code);
|
||||
return Isolate::Current()->stub_cache()->ComputeCallDebugBreak(argc,
|
||||
Code::CALL_IC);
|
||||
}
|
||||
|
||||
|
||||
@ -425,8 +422,8 @@ void CheckDebuggerUnloaded(bool check_functions) {
|
||||
CHECK_EQ(NULL, Isolate::Current()->debug()->debug_info_list_);
|
||||
|
||||
// Collect garbage to ensure weak handles are cleared.
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
||||
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
|
||||
|
||||
// Iterate the head and check that there are no debugger related objects left.
|
||||
HeapIterator iterator;
|
||||
|
Loading…
Reference in New Issue
Block a user