If CallNew targets a constant global, set its state to monomorphic
BUG= Review URL: https://codereview.chromium.org/1023103003 Cr-Commit-Position: refs/heads/master@{#27399}
This commit is contained in:
parent
310d75218e
commit
c46a937220
18
src/ast.cc
18
src/ast.cc
@ -622,24 +622,6 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
|
||||
}
|
||||
|
||||
|
||||
bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
|
||||
LookupIterator* it) {
|
||||
target_ = Handle<JSFunction>::null();
|
||||
DCHECK(it->IsFound() && it->GetHolder<JSObject>().is_identical_to(global));
|
||||
Handle<PropertyCell> cell = it->GetPropertyCell();
|
||||
if (cell->value()->IsJSFunction()) {
|
||||
Handle<JSFunction> candidate(JSFunction::cast(cell->value()));
|
||||
// If the function is in new space we assume it's more likely to
|
||||
// change and thus prefer the general IC code.
|
||||
if (!it->isolate()->heap()->InNewSpace(*candidate)) {
|
||||
target_ = candidate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation of AstVisitor
|
||||
|
||||
|
@ -1849,11 +1849,14 @@ class Call FINAL : public Expression {
|
||||
|
||||
Handle<AllocationSite> allocation_site() { return allocation_site_; }
|
||||
|
||||
void SetKnownGlobalTarget(Handle<JSFunction> target) {
|
||||
target_ = target;
|
||||
set_is_uninitialized(false);
|
||||
}
|
||||
void set_target(Handle<JSFunction> target) { target_ = target; }
|
||||
void set_allocation_site(Handle<AllocationSite> site) {
|
||||
allocation_site_ = site;
|
||||
}
|
||||
bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupIterator* it);
|
||||
|
||||
static int num_ids() { return parent_num_ids() + 2; }
|
||||
BailoutId ReturnId() const { return BailoutId(local_id(0)); }
|
||||
@ -1954,6 +1957,10 @@ class CallNew FINAL : public Expression {
|
||||
}
|
||||
void set_is_monomorphic(bool monomorphic) { is_monomorphic_ = monomorphic; }
|
||||
void set_target(Handle<JSFunction> target) { target_ = target; }
|
||||
void SetKnownGlobalTarget(Handle<JSFunction> target) {
|
||||
target_ = target;
|
||||
is_monomorphic_ = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
CallNew(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
|
||||
|
@ -9106,10 +9106,10 @@ bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildArrayCall(expr,
|
||||
expr->arguments()->length(),
|
||||
function,
|
||||
expr->allocation_site());
|
||||
Handle<AllocationSite> site = expr->allocation_site();
|
||||
if (site.is_null()) return false;
|
||||
|
||||
BuildArrayCall(expr, expr->arguments()->length(), function, site);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9231,58 +9231,21 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
||||
// evaluation of the arguments.
|
||||
CHECK_ALIVE(VisitForValue(expr->expression()));
|
||||
HValue* function = Top();
|
||||
if (expr->global_call()) {
|
||||
Variable* var = proxy->var();
|
||||
bool known_global_function = false;
|
||||
// If there is a global property cell for the name at compile time and
|
||||
// access check is not enabled we assume that the function will not change
|
||||
// and generate optimized code for calling the function.
|
||||
Handle<GlobalObject> global(current_info()->global_object());
|
||||
LookupIterator it(global, var->name(),
|
||||
LookupIterator::OWN_SKIP_INTERCEPTOR);
|
||||
GlobalPropertyAccess type = LookupGlobalProperty(var, &it, LOAD);
|
||||
if (type == kUseCell) {
|
||||
known_global_function = expr->ComputeGlobalTarget(global, &it);
|
||||
}
|
||||
if (known_global_function) {
|
||||
Add<HCheckValue>(function, expr->target());
|
||||
if (function->IsConstant() &&
|
||||
HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
|
||||
Handle<Object> constant = HConstant::cast(function)->handle(isolate());
|
||||
Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
|
||||
expr->SetKnownGlobalTarget(target);
|
||||
}
|
||||
|
||||
// Placeholder for the receiver.
|
||||
Push(graph()->GetConstantUndefined());
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
// Placeholder for the receiver.
|
||||
Push(graph()->GetConstantUndefined());
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
|
||||
// Patch the global object on the stack by the expected receiver.
|
||||
HValue* receiver = ImplicitReceiverFor(function, expr->target());
|
||||
const int receiver_index = argument_count - 1;
|
||||
environment()->SetExpressionStackAt(receiver_index, receiver);
|
||||
|
||||
if (TryInlineBuiltinFunctionCall(expr)) {
|
||||
if (FLAG_trace_inlining) {
|
||||
PrintF("Inlining builtin ");
|
||||
expr->target()->ShortPrint();
|
||||
PrintF("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TryInlineApiFunctionCall(expr, receiver)) return;
|
||||
if (TryHandleArrayCall(expr, function)) return;
|
||||
if (TryInlineCall(expr)) return;
|
||||
|
||||
PushArgumentsFromEnvironment(argument_count);
|
||||
call = BuildCallConstantFunction(expr->target(), argument_count);
|
||||
} else {
|
||||
Push(graph()->GetConstantUndefined());
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
PushArgumentsFromEnvironment(argument_count);
|
||||
call = New<HCallFunction>(function, argument_count);
|
||||
}
|
||||
|
||||
} else if (expr->IsMonomorphic()) {
|
||||
if (expr->IsMonomorphic()) {
|
||||
Add<HCheckValue>(function, expr->target());
|
||||
|
||||
Push(graph()->GetConstantUndefined());
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
|
||||
// Patch the global object on the stack by the expected receiver.
|
||||
HValue* receiver = ImplicitReceiverFor(function, expr->target());
|
||||
const int receiver_index = argument_count - 1;
|
||||
environment()->SetExpressionStackAt(receiver_index, receiver);
|
||||
@ -9296,15 +9259,12 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
||||
return;
|
||||
}
|
||||
if (TryInlineApiFunctionCall(expr, receiver)) return;
|
||||
|
||||
if (TryHandleArrayCall(expr, function)) return;
|
||||
if (TryInlineCall(expr)) return;
|
||||
|
||||
call = PreProcessCall(New<HInvokeFunction>(
|
||||
function, expr->target(), argument_count));
|
||||
|
||||
PushArgumentsFromEnvironment(argument_count);
|
||||
call = BuildCallConstantFunction(expr->target(), argument_count);
|
||||
} else {
|
||||
Push(graph()->GetConstantUndefined());
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
PushArgumentsFromEnvironment(argument_count);
|
||||
HCallFunction* call_function =
|
||||
New<HCallFunction>(function, argument_count);
|
||||
@ -9443,6 +9403,12 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
HValue* function = Top();
|
||||
CHECK_ALIVE(VisitExpressions(expr->arguments()));
|
||||
|
||||
if (function->IsConstant() &&
|
||||
HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
|
||||
Handle<Object> constant = HConstant::cast(function)->handle(isolate());
|
||||
expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
|
||||
}
|
||||
|
||||
if (FLAG_inline_construct &&
|
||||
expr->IsMonomorphic() &&
|
||||
IsAllocationInlineable(expr->target())) {
|
||||
|
Loading…
Reference in New Issue
Block a user