Commit be9b820c authored by rmcilroy's avatar rmcilroy Committed by Commit bot

Only treat possible eval calls going through 'with' as special.

This removes the POSSIBLY_EVAL_CALL call type, and instead uses OTHER_CALL
or WITH_CALL to decide whether to do the special LOOKUP_SLOT_CALL runtime
call to find the callee and possibly update the receiver with the with-object.
This means that eval calls out of 'with' blocks can now just do a normal
LdaLookupGlobalSlot operation, which can check the context chain for eval
extentions and fast-path the lookup if none exist.

BUG=661556

Review-Url: https://codereview.chromium.org/2487483004
Cr-Commit-Position: refs/heads/master@{#40965}
parent 8538143c
......@@ -900,9 +900,7 @@ void Call::AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
Call::CallType Call::GetCallType() const {
VariableProxy* proxy = expression()->AsVariableProxy();
if (proxy != NULL) {
if (is_possibly_eval()) {
return POSSIBLY_EVAL_CALL;
} else if (proxy->var()->IsUnallocated()) {
if (proxy->var()->IsUnallocated()) {
return GLOBAL_CALL;
} else if (proxy->var()->IsLookupSlot()) {
// Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
......
......@@ -1900,7 +1900,6 @@ class Call final : public Expression {
void MarkTail() { bit_field_ = IsTailField::update(bit_field_, true); }
enum CallType {
POSSIBLY_EVAL_CALL,
GLOBAL_CALL,
WITH_CALL,
NAMED_PROPERTY_CALL,
......
......@@ -2285,11 +2285,29 @@ void AstGraphBuilder::VisitCall(Call* expr) {
ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
Node* receiver_value = nullptr;
Node* callee_value = nullptr;
bool possibly_eval = false;
if (expr->is_possibly_eval()) {
if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
Variable* variable = callee->AsVariableProxy()->var();
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
Node* pair = NewNode(op, name);
callee_value = NewNode(common()->Projection(0), pair);
receiver_value = NewNode(common()->Projection(1), pair);
PrepareFrameState(pair, expr->LookupId(),
OutputFrameStateCombine::Push(2));
} else {
VisitForValue(callee);
callee_value = environment()->Pop();
receiver_hint = ConvertReceiverMode::kNullOrUndefined;
receiver_value = jsgraph()->UndefinedConstant();
}
} else {
switch (call_type) {
case Call::GLOBAL_CALL: {
VariableProxy* proxy = callee->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
VectorSlotPair pair =
CreateVectorSlotPair(proxy->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(proxy));
callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
pair, OutputFrameStateCombine::Push());
......@@ -2299,7 +2317,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
}
case Call::WITH_CALL: {
Variable* variable = callee->AsVariableProxy()->var();
DCHECK(variable->location() == VariableLocation::LOOKUP);
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
......@@ -2308,7 +2325,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
receiver_value = NewNode(common()->Projection(1), pair);
PrepareFrameState(pair, expr->LookupId(),
OutputFrameStateCombine::Push(2));
break;
}
case Call::NAMED_PROPERTY_CALL: {
Property* property = callee->AsProperty();
......@@ -2354,7 +2370,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
Node* home = environment()->Peek(1);
Node* object = environment()->Top();
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
callee_value =
BuildNamedSuperLoad(object, home, name, VectorSlotPair());
PrepareFrameState(callee_value, property->LoadId(),
OutputFrameStateCombine::Push());
// Note that a property call requires the receiver to be wrapped into
......@@ -2388,21 +2405,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
}
case Call::SUPER_CALL:
return VisitCallSuper(expr);
case Call::POSSIBLY_EVAL_CALL:
possibly_eval = true;
if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
Variable* variable = callee->AsVariableProxy()->var();
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
Node* pair = NewNode(op, name);
callee_value = NewNode(common()->Projection(0), pair);
receiver_value = NewNode(common()->Projection(1), pair);
PrepareFrameState(pair, expr->LookupId(),
OutputFrameStateCombine::Push(2));
break;
}
// Fall through.
case Call::OTHER_CALL:
VisitForValue(callee);
callee_value = environment()->Pop();
......@@ -2410,6 +2412,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
receiver_value = jsgraph()->UndefinedConstant();
break;
}
}
// The callee and the receiver both have to be pushed onto the operand stack
// before arguments are being evaluated.
......@@ -2422,7 +2425,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
// Resolve callee for a potential direct eval call. This block will mutate the
// callee value pushed onto the environment.
if (possibly_eval && args->length() > 0) {
if (expr->is_possibly_eval() && args->length() > 0) {
int arg_count = args->length();
// Extract callee and source string from the environment.
......@@ -2453,7 +2456,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
const Operator* call =
javascript()->CallFunction(args->length() + 2, frequency, feedback,
receiver_hint, expr->tail_call_mode());
PrepareEagerCheckpoint(possibly_eval ? expr->EvalId() : expr->CallId());
PrepareEagerCheckpoint(expr->is_possibly_eval() ? expr->EvalId()
: expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
// The callee passed to the call, we just need to push something here to
// satisfy the bailout location contract. The fullcodegen code will not
......
......@@ -1666,10 +1666,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType();
switch (call_type) {
case Call::POSSIBLY_EVAL_CALL:
if (expr->is_possibly_eval()) {
EmitPossiblyEvalCall(expr);
break;
} else {
switch (call_type) {
case Call::GLOBAL_CALL:
EmitCallWithLoadIC(expr);
break;
......@@ -1708,6 +1708,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
EmitCall(expr);
break;
}
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
......
......@@ -2391,9 +2391,8 @@ void BytecodeGenerator::VisitCall(Call* expr) {
builder()->StoreAccumulatorInRegister(callee);
break;
}
case Call::WITH_CALL:
case Call::POSSIBLY_EVAL_CALL: {
if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
case Call::WITH_CALL: {
DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
RegisterAllocationScope inner_register_scope(this);
Register name = register_allocator()->NewRegister();
......@@ -2408,14 +2407,10 @@ void BytecodeGenerator::VisitCall(Call* expr) {
result_pair);
break;
}
// Fall through.
DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
}
case Call::OTHER_CALL: {
case Call::OTHER_CALL:
builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
VisitForRegisterValue(callee_expr, callee);
break;
}
case Call::NAMED_SUPER_PROPERTY_CALL: {
Property* property = callee_expr->AsProperty();
VisitNamedSuperPropertyLoad(property, receiver);
......@@ -2439,8 +2434,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// Resolve callee for a potential direct eval call. This block will mutate the
// callee value.
if (call_type == Call::POSSIBLY_EVAL_CALL &&
expr->arguments()->length() > 0) {
if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
RegisterAllocationScope inner_register_scope(this);
// Set up arguments for ResolvePossiblyDirectEval by copying callee, source
// strings and function closure, and loading language and
......
......@@ -11,7 +11,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 82
bytecode array length: 81
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -24,9 +24,10 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateClosure), U8(0), U8(2),
/* 36 E> */ B(StaLookupSlotSloppy), U8(1),
/* 52 S> */ B(LdaConstant), U8(2),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 52 S> */ B(LdaUndefined),
B(Star), R(2),
/* 52 E> */ B(LdaLookupGlobalSlot), U8(2), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(3),
B(Star), R(3),
B(LdaZero),
......
......@@ -903,7 +903,7 @@ bytecodes: [
/* 3435 E> */ B(StaCurrentContextSlot), U8(255),
/* 3438 S> */ B(LdaUndefined),
B(Star), R(2),
/* 3438 E> */ B(LdaGlobal), U8(4),
B(LdaGlobal), U8(4),
B(Star), R(1),
/* 3438 E> */ B(Call), R(1), R(2), U8(1), U8(2),
/* 3454 S> */ B(LdaSmi), U8(100),
......
......@@ -11,7 +11,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 63
bytecode array length: 62
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -22,9 +22,10 @@ bytecodes: [
B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5),
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 34 S> */ B(LdaUndefined),
B(Star), R(2),
/* 41 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaZero),
......
......@@ -12,7 +12,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 67
bytecode array length: 66
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -23,9 +23,10 @@ bytecodes: [
B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5),
/* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 14 S> */ B(LdaUndefined),
B(Star), R(2),
/* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaZero),
......@@ -57,7 +58,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 68
bytecode array length: 67
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -68,9 +69,10 @@ bytecodes: [
B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5),
/* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 14 S> */ B(LdaUndefined),
B(Star), R(2),
/* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaZero),
......@@ -103,7 +105,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 67
bytecode array length: 66
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -116,9 +118,10 @@ bytecodes: [
/* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaSmi), U8(20),
/* 16 E> */ B(StaLookupSlotSloppy), U8(0),
/* 22 S> */ B(LdaConstant), U8(1),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 22 S> */ B(LdaUndefined),
B(Star), R(2),
/* 29 E> */ B(LdaLookupGlobalSlot), U8(1), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
B(LdaZero),
......@@ -154,7 +157,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 67
bytecode array length: 66
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -165,9 +168,10 @@ bytecodes: [
B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5),
/* 38 E> */ B(StackCheck),
/* 44 S> */ B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 44 S> */ B(LdaUndefined),
B(Star), R(2),
/* 44 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaZero),
......@@ -204,7 +208,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 67
bytecode array length: 66
bytecodes: [
B(CreateFunctionContext), U8(3),
B(PushContext), R(0),
......@@ -215,9 +219,10 @@ bytecodes: [
B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5),
/* 34 E> */ B(StackCheck),
/* 40 S> */ B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(4), U8(1), R(1),
/* 40 S> */ B(LdaUndefined),
B(Star), R(2),
/* 40 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaZero),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment