aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/ast-graph-builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/ast-graph-builder.cc')
-rw-r--r--src/compiler/ast-graph-builder.cc1579
1 files changed, 198 insertions, 1381 deletions
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index 1b7d1169..e199a032 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -17,7 +17,9 @@
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/state-values-utils.h"
-#include "src/compiler/type-hint-analyzer.h"
+#include "src/feedback-vector.h"
+#include "src/objects-inl.h"
+#include "src/objects/literal-objects.h"
namespace v8 {
namespace internal {
@@ -166,8 +168,6 @@ class AstGraphBuilder::ControlScope BASE_EMBEDDED {
void ReturnValue(Node* return_value);
void ThrowValue(Node* exception_value);
- class DeferredCommands;
-
protected:
enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
@@ -207,93 +207,6 @@ class AstGraphBuilder::ControlScope BASE_EMBEDDED {
int stack_height_;
};
-// Helper class for a try-finally control scope. It can record intercepted
-// control-flow commands that cause entry into a finally-block, and re-apply
-// them after again leaving that block. Special tokens are used to identify
-// paths going through the finally-block to dispatch after leaving the block.
-class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
- public:
- explicit DeferredCommands(AstGraphBuilder* owner)
- : owner_(owner),
- deferred_(owner->local_zone()),
- return_token_(nullptr),
- throw_token_(nullptr) {}
-
- // One recorded control-flow command.
- struct Entry {
- Command command; // The command type being applied on this path.
- Statement* statement; // The target statement for the command or {nullptr}.
- Node* token; // A token identifying this particular path.
- };
-
- // Records a control-flow command while entering the finally-block. This also
- // generates a new dispatch token that identifies one particular path.
- Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
- Node* token = nullptr;
- switch (cmd) {
- case CMD_BREAK:
- case CMD_CONTINUE:
- token = NewPathToken(dispenser_.GetBreakContinueToken());
- break;
- case CMD_THROW:
- if (throw_token_) return throw_token_;
- token = NewPathToken(TokenDispenserForFinally::kThrowToken);
- throw_token_ = token;
- break;
- case CMD_RETURN:
- if (return_token_) return return_token_;
- token = NewPathToken(TokenDispenserForFinally::kReturnToken);
- return_token_ = token;
- break;
- }
- DCHECK_NOT_NULL(token);
- deferred_.push_back({cmd, stmt, token});
- return token;
- }
-
- // Returns the dispatch token to be used to identify the implicit fall-through
- // path at the end of a try-block into the corresponding finally-block.
- Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
-
- // Applies all recorded control-flow commands after the finally-block again.
- // This generates a dynamic dispatch on the token from the entry point.
- void ApplyDeferredCommands(Node* token, Node* value) {
- SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
- dispatch.BeginSwitch();
- for (size_t i = 0; i < deferred_.size(); ++i) {
- Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
- dispatch.BeginLabel(static_cast<int>(i), condition);
- dispatch.EndLabel();
- }
- for (size_t i = 0; i < deferred_.size(); ++i) {
- dispatch.BeginCase(static_cast<int>(i));
- owner_->execution_control()->PerformCommand(
- deferred_[i].command, deferred_[i].statement, value);
- dispatch.EndCase();
- }
- dispatch.EndSwitch();
- }
-
- protected:
- Node* NewPathToken(int token_id) {
- return owner_->jsgraph()->Constant(token_id);
- }
- Node* NewPathTokenForImplicitFallThrough() {
- return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
- }
- Node* NewPathDispatchCondition(Node* t1, Node* t2) {
- return owner_->NewNode(
- owner_->javascript()->StrictEqual(CompareOperationHint::kAny), t1, t2);
- }
-
- private:
- TokenDispenserForFinally dispenser_;
- AstGraphBuilder* owner_;
- ZoneVector<Entry> deferred_;
- Node* return_token_;
- Node* throw_token_;
-};
-
// Control scope implementation for a BreakableStatement.
class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
@@ -356,65 +269,9 @@ class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
};
-// Control scope implementation for a TryCatchStatement.
-class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
- public:
- ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt,
- TryCatchBuilder* control)
- : ControlScope(owner), control_(control) {
- builder()->try_nesting_level_++; // Increment nesting.
- }
- ~ControlScopeForCatch() {
- builder()->try_nesting_level_--; // Decrement nesting.
- }
-
- protected:
- bool Execute(Command cmd, Statement* target, Node** value) override {
- switch (cmd) {
- case CMD_THROW:
- control_->Throw(*value);
- return true;
- case CMD_BREAK:
- case CMD_CONTINUE:
- case CMD_RETURN:
- break;
- }
- return false;
- }
-
- private:
- TryCatchBuilder* control_;
-};
-
-
-// Control scope implementation for a TryFinallyStatement.
-class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
- public:
- ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt,
- DeferredCommands* commands, TryFinallyBuilder* control)
- : ControlScope(owner), commands_(commands), control_(control) {
- builder()->try_nesting_level_++; // Increment nesting.
- }
- ~ControlScopeForFinally() {
- builder()->try_nesting_level_--; // Decrement nesting.
- }
-
- protected:
- bool Execute(Command cmd, Statement* target, Node** value) override {
- Node* token = commands_->RecordCommand(cmd, target, *value);
- control_->LeaveTry(token, *value);
- return true;
- }
-
- private:
- DeferredCommands* commands_;
- TryFinallyBuilder* control_;
-};
-
AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph, float invocation_frequency,
- LoopAssignmentAnalysis* loop,
- TypeHintAnalysis* type_hint_analysis)
+ LoopAssignmentAnalysis* loop)
: isolate_(info->isolate()),
local_zone_(local_zone),
info_(info),
@@ -425,12 +282,10 @@ AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
globals_(0, local_zone),
execution_control_(nullptr),
execution_context_(nullptr),
- try_nesting_level_(0),
input_buffer_size_(0),
input_buffer_(nullptr),
exit_controls_(local_zone),
loop_assignment_analysis_(loop),
- type_hint_analysis_(type_hint_analysis),
state_values_cache_(jsgraph),
liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
false, local_zone),
@@ -453,7 +308,7 @@ Node* AstGraphBuilder::GetFunctionClosureForContext() {
// calling eval, not the anonymous closure containing the eval code.
const Operator* op =
javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
- return NewNode(op, current_context());
+ return NewNode(op);
} else {
DCHECK(closure_scope->is_function_scope());
return GetFunctionClosure();
@@ -483,18 +338,6 @@ Node* AstGraphBuilder::GetFunctionContext() {
return function_context_.get();
}
-
-Node* AstGraphBuilder::GetNewTarget() {
- if (!new_target_.is_set()) {
- int params = info()->num_parameters_including_this();
- int index = Linkage::GetJSCallNewTargetParamIndex(params);
- const Operator* op = common()->Parameter(index, "%new.target");
- Node* node = NewNode(op, graph()->start());
- new_target_.set(node);
- }
- return new_target_.get();
-}
-
Node* AstGraphBuilder::GetEmptyFrameState() {
if (!empty_frame_state_.is_set()) {
const Operator* op = common()->FrameState(
@@ -573,15 +416,10 @@ void AstGraphBuilder::CreateGraphBody(bool stack_check) {
// Build the arguments object if it is used.
BuildArgumentsObject(scope->arguments());
- // Build rest arguments array if it is used.
- Variable* rest_parameter = scope->rest_parameter();
- BuildRestArgumentsArray(rest_parameter);
-
- // Build assignment to {.this_function} variable if it is used.
- BuildThisFunctionVariable(scope->this_function_var());
-
- // Build assignment to {new.target} variable if it is used.
- BuildNewTargetVariable(scope->new_target_var());
+ // We don't support new.target and rest parameters here.
+ DCHECK_NULL(scope->new_target_var());
+ DCHECK_NULL(scope->rest_parameter());
+ DCHECK_NULL(scope->this_function_var());
// Emit tracing call if requested to do so.
if (FLAG_trace) {
@@ -835,7 +673,7 @@ void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
}
}
if (should_update) {
- const Operator* op = common()->StateValues(count);
+ const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
(*state_values) = graph()->NewNode(op, count, env_values);
}
}
@@ -1092,10 +930,12 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
switch (variable->location()) {
case VariableLocation::UNALLOCATED: {
DCHECK(!variable->binding_needs_init());
- FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
+ globals()->push_back(variable->name());
+ FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
DCHECK(!slot.IsInvalid());
globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
globals()->push_back(isolate()->factory()->undefined_value());
+ globals()->push_back(isolate()->factory()->undefined_value());
break;
}
case VariableLocation::PARAMETER:
@@ -1109,17 +949,10 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
if (variable->binding_needs_init()) {
Node* value = jsgraph()->TheHoleConstant();
const Operator* op = javascript()->StoreContext(0, variable->index());
- NewNode(op, current_context(), value);
+ NewNode(op, value);
}
break;
- case VariableLocation::LOOKUP: {
- DCHECK(!variable->binding_needs_init());
- Node* name = jsgraph()->Constant(variable->name());
- const Operator* op = javascript()->CallRuntime(Runtime::kDeclareEvalVar);
- Node* store = NewNode(op, name);
- PrepareFrameState(store, decl->proxy()->id());
- break;
- }
+ case VariableLocation::LOOKUP:
case VariableLocation::MODULE:
UNREACHABLE();
}
@@ -1134,9 +967,16 @@ void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
decl->fun(), info()->script(), info());
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
- FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
+ globals()->push_back(variable->name());
+ FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
DCHECK(!slot.IsInvalid());
globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
+
+ // We need the slot where the literals array lives, too.
+ slot = decl->fun()->LiteralFeedbackSlot();
+ DCHECK(!slot.IsInvalid());
+ globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
+
globals()->push_back(function);
break;
}
@@ -1151,19 +991,10 @@ void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
VisitForValue(decl->fun());
Node* value = environment()->Pop();
const Operator* op = javascript()->StoreContext(0, variable->index());
- NewNode(op, current_context(), value);
- break;
- }
- case VariableLocation::LOOKUP: {
- VisitForValue(decl->fun());
- Node* value = environment()->Pop();
- Node* name = jsgraph()->Constant(variable->name());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kDeclareEvalFunction);
- Node* store = NewNode(op, name, value);
- PrepareFrameState(store, decl->proxy()->id());
+ NewNode(op, value);
break;
}
+ case VariableLocation::LOOKUP:
case VariableLocation::MODULE:
UNREACHABLE();
}
@@ -1240,14 +1071,8 @@ void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
- VisitForValue(stmt->expression());
- Node* value = environment()->Pop();
- Node* object = BuildToObject(value, stmt->ToObjectId());
- Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
- const Operator* op = javascript()->CreateWithContext(scope_info);
- Node* context = NewNode(op, object, GetFunctionClosureForContext());
- PrepareFrameState(context, stmt->EntryId());
- VisitInScope(stmt->statement(), stmt->scope(), context);
+ // Dynamic scoping is supported only by going through Ignition first.
+ UNREACHABLE();
}
@@ -1277,13 +1102,7 @@ void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
Node* label = environment()->Pop();
Node* tag = environment()->Top();
- CompareOperationHint hint;
- if (!type_hint_analysis_ ||
- !type_hint_analysis_->GetCompareOperationHint(clause->CompareId(),
- &hint)) {
- hint = CompareOperationHint::kAny;
- }
-
+ CompareOperationHint hint = CompareOperationHint::kAny;
const Operator* op = javascript()->StrictEqual(hint);
Node* condition = NewNode(op, tag, label);
compare_switch.BeginLabel(i, condition);
@@ -1354,218 +1173,32 @@ void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
- VisitForValue(stmt->subject());
- Node* object = environment()->Pop();
- BlockBuilder for_block(this);
- for_block.BeginBlock();
- // Check for null or undefined before entering loop.
- Node* is_null_cond =
- NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), object,
- jsgraph()->NullConstant());
- for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
- Node* is_undefined_cond =
- NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), object,
- jsgraph()->UndefinedConstant());
- for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
- {
- // Convert object to jsobject.
- object = BuildToObject(object, stmt->ToObjectId());
- environment()->Push(object);
-
- // Prepare for-in cache.
- Node* prepare = NewNode(javascript()->ForInPrepare(), object);
- PrepareFrameState(prepare, stmt->PrepareId(),
- OutputFrameStateCombine::Push(3));
- Node* cache_type = NewNode(common()->Projection(0), prepare);
- Node* cache_array = NewNode(common()->Projection(1), prepare);
- Node* cache_length = NewNode(common()->Projection(2), prepare);
-
- // Construct the rest of the environment.
- environment()->Push(cache_type);
- environment()->Push(cache_array);
- environment()->Push(cache_length);
- environment()->Push(jsgraph()->ZeroConstant());
-
- // Build the actual loop body.
- LoopBuilder for_loop(this);
- for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
- {
- // These stack values are renamed in the case of OSR, so reload them
- // from the environment.
- Node* index = environment()->Peek(0);
- Node* cache_length = environment()->Peek(1);
- Node* cache_array = environment()->Peek(2);
- Node* cache_type = environment()->Peek(3);
- Node* object = environment()->Peek(4);
-
- // Check loop termination condition (we know that the {index} is always
- // in Smi range, so we can just set the hint on the comparison below).
- PrepareEagerCheckpoint(stmt->EntryId());
- Node* exit_cond =
- NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall),
- index, cache_length);
- PrepareFrameState(exit_cond, BailoutId::None());
- for_loop.BreakUnless(exit_cond);
-
- // Compute the next enumerated value.
- Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
- cache_type, index);
- PrepareFrameState(value, stmt->FilterId(),
- OutputFrameStateCombine::Push());
- IfBuilder test_value(this);
- Node* test_value_cond =
- NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), value,
- jsgraph()->UndefinedConstant());
- test_value.If(test_value_cond, BranchHint::kFalse);
- test_value.Then();
- test_value.Else();
- {
- environment()->Push(value);
- PrepareEagerCheckpoint(stmt->FilterId());
- value = environment()->Pop();
- // Bind value and do loop body.
- VectorSlotPair feedback =
- CreateVectorSlotPair(stmt->EachFeedbackSlot());
- VisitForInAssignment(stmt->each(), value, feedback,
- stmt->AssignmentId());
- VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
- }
- test_value.End();
- for_loop.EndBody();
-
- // Increment counter and continue (we know that the {index} is always
- // in Smi range, so we can just set the hint on the increment below).
- index = environment()->Peek(0);
- PrepareEagerCheckpoint(stmt->IncrementId());
- index = NewNode(javascript()->Add(BinaryOperationHint::kSignedSmall),
- index, jsgraph()->OneConstant());
- PrepareFrameState(index, BailoutId::None());
- environment()->Poke(0, index);
- }
- for_loop.EndLoop();
- environment()->Drop(5);
- }
- for_block.EndBlock();
+ // Only the BytecodeGraphBuilder supports for-in.
+ return SetStackOverflow();
}
void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
- LoopBuilder for_loop(this);
- VisitForEffect(stmt->assign_iterator());
- for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
- VisitForEffect(stmt->next_result());
- VisitForTest(stmt->result_done());
- Node* condition = environment()->Pop();
- for_loop.BreakWhen(condition);
- VisitForEffect(stmt->assign_each());
- VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
- for_loop.EndBody();
- for_loop.EndLoop();
+ // Iterator looping is supported only by going through Ignition first.
+ UNREACHABLE();
}
void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
- TryCatchBuilder try_control(this);
-
- // Evaluate the try-block inside a control scope. This simulates a handler
- // that is intercepting 'throw' control commands.
- try_control.BeginTry();
- {
- ControlScopeForCatch scope(this, stmt, &try_control);
- STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
- environment()->Push(current_context());
- Visit(stmt->try_block());
- environment()->Pop();
- }
- try_control.EndTry();
-
- // If requested, clear message object as we enter the catch block.
- if (stmt->clear_pending_message()) {
- Node* the_hole = jsgraph()->TheHoleConstant();
- NewNode(javascript()->StoreMessage(), the_hole);
- }
-
- // Create a catch scope that binds the exception.
- Node* exception = try_control.GetExceptionNode();
- Handle<String> name = stmt->variable()->name();
- Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
- const Operator* op = javascript()->CreateCatchContext(name, scope_info);
- Node* context = NewNode(op, exception, GetFunctionClosureForContext());
-
- // Evaluate the catch-block.
- VisitInScope(stmt->catch_block(), stmt->scope(), context);
- try_control.EndCatch();
+ // Exception handling is supported only by going through Ignition first.
+ UNREACHABLE();
}
void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
- TryFinallyBuilder try_control(this);
-
- // We keep a record of all paths that enter the finally-block to be able to
- // dispatch to the correct continuation point after the statements in the
- // finally-block have been evaluated.
- //
- // The try-finally construct can enter the finally-block in three ways:
- // 1. By exiting the try-block normally, falling through at the end.
- // 2. By exiting the try-block with a function-local control flow transfer
- // (i.e. through break/continue/return statements).
- // 3. By exiting the try-block with a thrown exception.
- Node* fallthrough_result = jsgraph()->TheHoleConstant();
- ControlScope::DeferredCommands* commands =
- new (local_zone()) ControlScope::DeferredCommands(this);
-
- // Evaluate the try-block inside a control scope. This simulates a handler
- // that is intercepting all control commands.
- try_control.BeginTry();
- {
- ControlScopeForFinally scope(this, stmt, commands, &try_control);
- STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
- environment()->Push(current_context());
- Visit(stmt->try_block());
- environment()->Pop();
- }
- try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
-
- // The result value semantics depend on how the block was entered:
- // - ReturnStatement: It represents the return value being returned.
- // - ThrowStatement: It represents the exception being thrown.
- // - BreakStatement/ContinueStatement: Filled with the hole.
- // - Falling through into finally-block: Filled with the hole.
- Node* result = try_control.GetResultValueNode();
- Node* token = try_control.GetDispatchTokenNode();
-
- // The result value, dispatch token and message is expected on the operand
- // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
- Node* message = NewNode(javascript()->LoadMessage());
- environment()->Push(token);
- environment()->Push(result);
- environment()->Push(message);
-
- // Clear message object as we enter the finally block.
- Node* the_hole = jsgraph()->TheHoleConstant();
- NewNode(javascript()->StoreMessage(), the_hole);
-
- // Evaluate the finally-block.
- Visit(stmt->finally_block());
- try_control.EndFinally();
-
- // The result value, dispatch token and message is restored from the operand
- // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
- message = environment()->Pop();
- result = environment()->Pop();
- token = environment()->Pop();
- NewNode(javascript()->StoreMessage(), message);
-
- // Dynamic dispatch after the finally-block.
- commands->ApplyDeferredCommands(token, result);
+ // Exception handling is supported only by going through Ignition first.
+ UNREACHABLE();
}
void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
- Node* node =
- NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
- PrepareFrameState(node, stmt->DebugBreakId());
- environment()->MarkAllLocalsLive();
+ // Debugger statement is supported only by going through Ignition first.
+ UNREACHABLE();
}
@@ -1577,112 +1210,14 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
// Create node to instantiate a new closure.
PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
- const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
+ VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
+ const Operator* op =
+ javascript()->CreateClosure(shared_info, pair, pretenure);
Node* value = NewNode(op);
ast_context()->ProduceValue(expr, value);
}
-
-void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
- VisitForValueOrTheHole(expr->extends());
- VisitForValue(expr->constructor());
-
- // Create node to instantiate a new class.
- Node* constructor = environment()->Pop();
- Node* extends = environment()->Pop();
- Node* start = jsgraph()->Constant(expr->start_position());
- Node* end = jsgraph()->Constant(expr->end_position());
- const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
- Node* literal = NewNode(opc, extends, constructor, start, end);
- PrepareFrameState(literal, expr->CreateLiteralId(),
- OutputFrameStateCombine::Push());
- environment()->Push(literal);
-
- // Load the "prototype" from the constructor.
- PrepareEagerCheckpoint(expr->CreateLiteralId());
- Handle<Name> name = isolate()->factory()->prototype_string();
- VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
- Node* prototype = BuildNamedLoad(literal, name, pair);
- PrepareFrameState(prototype, expr->PrototypeId(),
- OutputFrameStateCombine::Push());
- environment()->Push(prototype);
-
- // Create nodes to store method values into the literal.
- for (int i = 0; i < expr->properties()->length(); i++) {
- ClassLiteral::Property* property = expr->properties()->at(i);
- environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
-
- VisitForValue(property->key());
- Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
- environment()->Push(name);
-
- // The static prototype property is read only. We handle the non computed
- // property name case in the parser. Since this is the only case where we
- // need to check for an own read only property we special case this so we do
- // not need to do this for every property.
- if (property->is_static() && property->is_computed_name()) {
- Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
- expr->GetIdForProperty(i));
- environment()->Push(check);
- }
-
- VisitForValue(property->value());
- Node* value = environment()->Pop();
- Node* key = environment()->Pop();
- Node* receiver = environment()->Pop();
-
- BuildSetHomeObject(value, receiver, property);
-
- switch (property->kind()) {
- case ClassLiteral::Property::METHOD: {
- Node* attr = jsgraph()->Constant(DONT_ENUM);
- Node* set_function_name =
- jsgraph()->Constant(property->NeedsSetFunctionName());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
- Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
- PrepareFrameState(call, BailoutId::None());
- break;
- }
- case ClassLiteral::Property::GETTER: {
- Node* attr = jsgraph()->Constant(DONT_ENUM);
- const Operator* op = javascript()->CallRuntime(
- Runtime::kDefineGetterPropertyUnchecked, 4);
- NewNode(op, receiver, key, value, attr);
- break;
- }
- case ClassLiteral::Property::SETTER: {
- Node* attr = jsgraph()->Constant(DONT_ENUM);
- const Operator* op = javascript()->CallRuntime(
- Runtime::kDefineSetterPropertyUnchecked, 4);
- NewNode(op, receiver, key, value, attr);
- break;
- }
- case ClassLiteral::Property::FIELD: {
- UNREACHABLE();
- break;
- }
- }
- }
-
- // Set the constructor to have fast properties.
- prototype = environment()->Pop();
- literal = environment()->Pop();
- const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
- literal = NewNode(op, literal);
-
- // Assign to class variable.
- if (expr->class_variable_proxy() != nullptr) {
- Variable* var = expr->class_variable_proxy()->var();
- VectorSlotPair feedback = CreateVectorSlotPair(
- expr->NeedsProxySlot() ? expr->ProxySlot()
- : FeedbackVectorSlot::Invalid());
- BuildVariableAssignment(var, literal, Token::INIT, feedback,
- BailoutId::None());
- }
- ast_context()->ProduceValue(expr, literal);
-}
-
+void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); }
void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
UNREACHABLE();
@@ -1734,7 +1269,8 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
// Create node to materialize a regular expression literal.
const Operator* op = javascript()->CreateLiteralRegExp(
- expr->pattern(), expr->flags(), expr->literal_index());
+ expr->pattern(), expr->flags(),
+ FeedbackVector::GetIndex(expr->literal_slot()));
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(expr, literal);
@@ -1746,8 +1282,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
// Create node to deep-copy the literal boilerplate.
const Operator* op = javascript()->CreateLiteralObject(
- expr->constant_properties(), expr->ComputeFlags(true),
- expr->literal_index(), expr->properties_count());
+ expr->GetOrBuildConstantProperties(isolate()), expr->ComputeFlags(true),
+ FeedbackVector::GetIndex(expr->literal_slot()), expr->properties_count());
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
@@ -1757,15 +1293,15 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
environment()->Push(literal);
// Create nodes to store computed values into the literal.
- int property_index = 0;
AccessorTable accessor_table(local_zone());
- for (; property_index < expr->properties()->length(); property_index++) {
- ObjectLiteral::Property* property = expr->properties()->at(property_index);
- if (property->is_computed_name()) break;
+ for (int i = 0; i < expr->properties()->length(); i++) {
+ ObjectLiteral::Property* property = expr->properties()->at(i);
+ DCHECK(!property->is_computed_name());
if (property->IsCompileTimeValue()) continue;
Literal* key = property->key()->AsLiteral();
switch (property->kind()) {
+ case ObjectLiteral::Property::SPREAD:
case ObjectLiteral::Property::CONSTANT:
UNREACHABLE();
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
@@ -1783,7 +1319,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Handle<Name> name = key->AsPropertyName();
VectorSlotPair feedback =
CreateVectorSlotPair(property->GetSlot(0));
- Node* store = BuildNamedStore(literal, name, value, feedback);
+ Node* store = BuildNamedStoreOwn(literal, name, value, feedback);
PrepareFrameState(store, key->id(),
OutputFrameStateCombine::Ignore());
BuildSetHomeObject(value, literal, property, 1);
@@ -1818,21 +1354,20 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Node* set_prototype = NewNode(op, receiver, value);
// SetPrototype should not lazy deopt on an object literal.
- PrepareFrameState(set_prototype,
- expr->GetIdForPropertySet(property_index));
+ PrepareFrameState(set_prototype, expr->GetIdForPropertySet(i));
break;
}
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
- it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+ it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
- it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+ it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@@ -1856,77 +1391,6 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* call = NewNode(op, literal, name, getter, setter, attr);
PrepareFrameState(call, it->second->bailout_id);
}
-
- // Object literals have two parts. The "static" part on the left contains no
- // computed property names, and so we can compute its map ahead of time; see
- // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
- // with the first computed property name and continues with all properties to
- // its right. All the code from above initializes the static component of the
- // object literal, and arranges for the map of the result to reflect the
- // static order in which the keys appear. For the dynamic properties, we
- // compile them into a series of "SetOwnProperty" runtime calls. This will
- // preserve insertion order.
- for (; property_index < expr->properties()->length(); property_index++) {
- ObjectLiteral::Property* property = expr->properties()->at(property_index);
-
- if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
- environment()->Push(environment()->Top()); // Duplicate receiver.
- VisitForValue(property->value());
- Node* value = environment()->Pop();
- Node* receiver = environment()->Pop();
- const Operator* op =
- javascript()->CallRuntime(Runtime::kInternalSetPrototype);
- Node* call = NewNode(op, receiver, value);
- PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
- continue;
- }
-
- environment()->Push(environment()->Top()); // Duplicate receiver.
- VisitForValue(property->key());
- Node* name = BuildToName(environment()->Pop(),
- expr->GetIdForPropertyName(property_index));
- environment()->Push(name);
- VisitForValue(property->value());
- Node* value = environment()->Pop();
- Node* key = environment()->Pop();
- Node* receiver = environment()->Pop();
- BuildSetHomeObject(value, receiver, property);
- switch (property->kind()) {
- case ObjectLiteral::Property::CONSTANT:
- case ObjectLiteral::Property::COMPUTED:
- case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
- if (!property->emit_store()) continue;
- Node* attr = jsgraph()->Constant(NONE);
- Node* set_function_name =
- jsgraph()->Constant(property->NeedsSetFunctionName());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
- Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
- PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
- break;
- }
- case ObjectLiteral::Property::PROTOTYPE:
- UNREACHABLE(); // Handled specially above.
- break;
- case ObjectLiteral::Property::GETTER: {
- Node* attr = jsgraph()->Constant(NONE);
- const Operator* op = javascript()->CallRuntime(
- Runtime::kDefineGetterPropertyUnchecked, 4);
- Node* call = NewNode(op, receiver, key, value, attr);
- PrepareFrameState(call, BailoutId::None());
- break;
- }
- case ObjectLiteral::Property::SETTER: {
- Node* attr = jsgraph()->Constant(NONE);
- const Operator* op = javascript()->CallRuntime(
- Runtime::kDefineSetterPropertyUnchecked, 4);
- Node* call = NewNode(op, receiver, key, value, attr);
- PrepareFrameState(call, BailoutId::None());
- break;
- }
- }
- }
-
ast_context()->ProduceValue(expr, environment()->Pop());
}
@@ -1947,8 +1411,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
// Create node to deep-copy the literal boilerplate.
const Operator* op = javascript()->CreateLiteralArray(
- expr->constant_elements(), expr->ComputeFlags(true),
- expr->literal_index(), expr->values()->length());
+ expr->GetOrBuildConstantElements(isolate()), expr->ComputeFlags(true),
+ FeedbackVector::GetIndex(expr->literal_slot()), expr->values()->length());
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
@@ -1978,72 +1442,6 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
ast_context()->ProduceValue(expr, environment()->Pop());
}
-void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
- const VectorSlotPair& feedback,
- BailoutId bailout_id) {
- DCHECK(expr->IsValidReferenceExpressionOrThis());
-
- // Left-hand side can only be a property, a global or a variable slot.
- Property* property = expr->AsProperty();
- LhsKind assign_type = Property::GetAssignType(property);
-
- // Evaluate LHS expression and store the value.
- switch (assign_type) {
- case VARIABLE: {
- Variable* var = expr->AsVariableProxy()->var();
- BuildVariableAssignment(var, value, Token::ASSIGN, feedback, bailout_id);
- break;
- }
- case NAMED_PROPERTY: {
- environment()->Push(value);
- VisitForValue(property->obj());
- Node* object = environment()->Pop();
- value = environment()->Pop();
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- Node* store = BuildNamedStore(object, name, value, feedback);
- PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
- break;
- }
- case KEYED_PROPERTY: {
- environment()->Push(value);
- VisitForValue(property->obj());
- VisitForValue(property->key());
- Node* key = environment()->Pop();
- Node* object = environment()->Pop();
- value = environment()->Pop();
- Node* store = BuildKeyedStore(object, key, value, feedback);
- PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
- break;
- }
- case NAMED_SUPER_PROPERTY: {
- environment()->Push(value);
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- value = environment()->Pop();
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
- PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- environment()->Push(value);
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- VisitForValue(property->key());
- Node* key = environment()->Pop();
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- value = environment()->Pop();
- Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
- PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
- break;
- }
- }
-}
-
-
void AstGraphBuilder::VisitAssignment(Assignment* expr) {
DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
@@ -2071,13 +1469,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VisitForValue(property->key());
break;
case NAMED_SUPER_PROPERTY:
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- break;
case KEYED_SUPER_PROPERTY:
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- VisitForValue(property->key());
+ UNREACHABLE();
break;
}
@@ -2115,28 +1508,10 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
OutputFrameStateCombine::Push());
break;
}
- case NAMED_SUPER_PROPERTY: {
- Node* home_object = environment()->Top();
- Node* receiver = environment()->Peek(1);
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- VectorSlotPair pair =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
- PrepareFrameState(old_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- Node* key = environment()->Top();
- Node* home_object = environment()->Peek(1);
- Node* receiver = environment()->Peek(2);
- VectorSlotPair pair =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
- PrepareFrameState(old_value, property->LoadId(),
- OutputFrameStateCombine::Push());
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNREACHABLE();
break;
- }
}
environment()->Push(old_value);
VisitForValue(expr->value());
@@ -2181,22 +1556,10 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
OutputFrameStateCombine::Push());
break;
}
- case NAMED_SUPER_PROPERTY: {
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
- PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- Node* key = environment()->Pop();
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
- PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNREACHABLE();
break;
- }
}
ast_context()->ProduceValue(expr, value);
@@ -2205,8 +1568,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
void AstGraphBuilder::VisitYield(Yield* expr) {
// Generator functions are supported only by going through Ignition first.
- SetStackOverflow();
- ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
+ UNREACHABLE();
}
@@ -2243,27 +1605,10 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
break;
}
- case NAMED_SUPER_PROPERTY: {
- VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
- value = BuildNamedSuperLoad(receiver, home_object, name, pair);
- PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
- VisitForValue(expr->key());
- Node* key = environment()->Pop();
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
- PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNREACHABLE();
break;
- }
}
ast_context()->ProduceValue(expr, value);
}
@@ -2272,140 +1617,70 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
void AstGraphBuilder::VisitCall(Call* expr) {
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType();
+ CHECK(!expr->is_possibly_eval());
// Prepare the callee and the receiver to the function call. This depends on
// the semantics of the underlying call type.
ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
Node* receiver_value = nullptr;
Node* callee_value = nullptr;
- 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();
+ switch (call_type) {
+ case Call::GLOBAL_CALL: {
+ VariableProxy* proxy = callee->AsVariableProxy();
+ VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
+ PrepareEagerCheckpoint(BeforeId(proxy));
+ callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
+ pair, OutputFrameStateCombine::Push());
receiver_hint = ConvertReceiverMode::kNullOrUndefined;
receiver_value = jsgraph()->UndefinedConstant();
+ break;
}
- } else {
- switch (call_type) {
- case Call::GLOBAL_CALL: {
- VariableProxy* proxy = callee->AsVariableProxy();
- VectorSlotPair pair =
- CreateVectorSlotPair(proxy->VariableFeedbackSlot());
- PrepareEagerCheckpoint(BeforeId(proxy));
- callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
- pair, OutputFrameStateCombine::Push());
- receiver_hint = ConvertReceiverMode::kNullOrUndefined;
- receiver_value = jsgraph()->UndefinedConstant();
- break;
- }
- case Call::WITH_CALL: {
- 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;
- }
- case Call::NAMED_PROPERTY_CALL: {
- Property* property = callee->AsProperty();
- VectorSlotPair feedback =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- VisitForValue(property->obj());
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- Node* object = environment()->Top();
- callee_value = BuildNamedLoad(object, name, feedback);
- PrepareFrameState(callee_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- // Note that a property call requires the receiver to be wrapped into
- // an object for sloppy callees. However the receiver is guaranteed
- // not to be null or undefined at this point.
- receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
- receiver_value = environment()->Pop();
- break;
- }
- case Call::KEYED_PROPERTY_CALL: {
- Property* property = callee->AsProperty();
- VectorSlotPair feedback =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- VisitForValue(property->obj());
- VisitForValue(property->key());
- Node* key = environment()->Pop();
- Node* object = environment()->Top();
- callee_value = BuildKeyedLoad(object, key, feedback);
- PrepareFrameState(callee_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- // Note that a property call requires the receiver to be wrapped into
- // an object for sloppy callees. However the receiver is guaranteed
- // not to be null or undefined at this point.
- receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
- receiver_value = environment()->Pop();
- break;
- }
- case Call::NAMED_SUPER_PROPERTY_CALL: {
- Property* property = callee->AsProperty();
- SuperPropertyReference* super_ref =
- property->obj()->AsSuperPropertyReference();
- VisitForValue(super_ref->home_object());
- VisitForValue(super_ref->this_var());
- Node* home = environment()->Peek(1);
- Node* object = environment()->Top();
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- 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
- // an object for sloppy callees. Since the receiver is not the target of
- // the load, it could very well be null or undefined at this point.
- receiver_value = environment()->Pop();
- environment()->Drop(1);
- break;
- }
- case Call::KEYED_SUPER_PROPERTY_CALL: {
- Property* property = callee->AsProperty();
- SuperPropertyReference* super_ref =
- property->obj()->AsSuperPropertyReference();
- VisitForValue(super_ref->home_object());
- VisitForValue(super_ref->this_var());
- environment()->Push(environment()->Top()); // Duplicate this_var.
- environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
- VisitForValue(property->key());
- Node* key = environment()->Pop();
- Node* home = environment()->Pop();
- Node* object = environment()->Pop();
- callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
- PrepareFrameState(callee_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- // Note that a property call requires the receiver to be wrapped into
- // an object for sloppy callees. Since the receiver is not the target of
- // the load, it could very well be null or undefined at this point.
- receiver_value = environment()->Pop();
- environment()->Drop(1);
- break;
- }
- case Call::SUPER_CALL:
- return VisitCallSuper(expr);
- case Call::OTHER_CALL:
- VisitForValue(callee);
- callee_value = environment()->Pop();
- receiver_hint = ConvertReceiverMode::kNullOrUndefined;
- receiver_value = jsgraph()->UndefinedConstant();
- break;
+ case Call::NAMED_PROPERTY_CALL: {
+ Property* property = callee->AsProperty();
+ VectorSlotPair feedback =
+ CreateVectorSlotPair(property->PropertyFeedbackSlot());
+ VisitForValue(property->obj());
+ Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
+ Node* object = environment()->Top();
+ callee_value = BuildNamedLoad(object, name, feedback);
+ PrepareFrameState(callee_value, property->LoadId(),
+ OutputFrameStateCombine::Push());
+ // Note that a property call requires the receiver to be wrapped into
+ // an object for sloppy callees. However the receiver is guaranteed
+ // not to be null or undefined at this point.
+ receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
+ receiver_value = environment()->Pop();
+ break;
+ }
+ case Call::KEYED_PROPERTY_CALL: {
+ Property* property = callee->AsProperty();
+ VectorSlotPair feedback =
+ CreateVectorSlotPair(property->PropertyFeedbackSlot());
+ VisitForValue(property->obj());
+ VisitForValue(property->key());
+ Node* key = environment()->Pop();
+ Node* object = environment()->Top();
+ callee_value = BuildKeyedLoad(object, key, feedback);
+ PrepareFrameState(callee_value, property->LoadId(),
+ OutputFrameStateCombine::Push());
+ // Note that a property call requires the receiver to be wrapped into
+ // an object for sloppy callees. However the receiver is guaranteed
+ // not to be null or undefined at this point.
+ receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
+ receiver_value = environment()->Pop();
+ break;
}
+ case Call::OTHER_CALL:
+ VisitForValue(callee);
+ callee_value = environment()->Pop();
+ receiver_hint = ConvertReceiverMode::kNullOrUndefined;
+ receiver_value = jsgraph()->UndefinedConstant();
+ break;
+ case Call::NAMED_SUPER_PROPERTY_CALL:
+ case Call::KEYED_SUPER_PROPERTY_CALL:
+ case Call::SUPER_CALL:
+ case Call::WITH_CALL:
+ UNREACHABLE();
}
// The callee and the receiver both have to be pushed onto the operand stack
@@ -2417,41 +1692,13 @@ void AstGraphBuilder::VisitCall(Call* expr) {
ZoneList<Expression*>* args = expr->arguments();
VisitForValues(args);
- // Resolve callee for a potential direct eval call. This block will mutate the
- // callee value pushed onto the environment.
- if (expr->is_possibly_eval() && args->length() > 0) {
- int arg_count = args->length();
-
- // Extract callee and source string from the environment.
- Node* callee = environment()->Peek(arg_count + 1);
- Node* source = environment()->Peek(arg_count - 1);
-
- // Create node to ask for help resolving potential eval call. This will
- // provide a fully resolved callee to patch into the environment.
- Node* function = GetFunctionClosure();
- Node* language = jsgraph()->Constant(language_mode());
- Node* eval_scope_position =
- jsgraph()->Constant(current_scope()->start_position());
- Node* eval_position = jsgraph()->Constant(expr->position());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
- Node* new_callee = NewNode(op, callee, source, function, language,
- eval_scope_position, eval_position);
- PrepareFrameState(new_callee, expr->EvalId(),
- OutputFrameStateCombine::PokeAt(arg_count + 1));
-
- // Patch callee on the environment.
- environment()->Poke(arg_count + 1, new_callee);
- }
-
// Create node to perform the function call.
float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot());
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
const Operator* call =
- javascript()->CallFunction(args->length() + 2, frequency, feedback,
- receiver_hint, expr->tail_call_mode());
- PrepareEagerCheckpoint(expr->is_possibly_eval() ? expr->EvalId()
- : expr->CallId());
+ javascript()->Call(args->length() + 2, frequency, feedback, receiver_hint,
+ expr->tail_call_mode());
+ PrepareEagerCheckpoint(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
@@ -2463,34 +1710,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
}
-void AstGraphBuilder::VisitCallSuper(Call* expr) {
- SuperCallReference* super = expr->expression()->AsSuperCallReference();
- DCHECK_NOT_NULL(super);
-
- // Prepare the callee to the super call.
- VisitForValue(super->this_function_var());
- Node* this_function = environment()->Pop();
- const Operator* op =
- javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
- Node* super_function = NewNode(op, this_function);
- environment()->Push(super_function);
-
- // Evaluate all arguments to the super call.
- ZoneList<Expression*>* args = expr->arguments();
- VisitForValues(args);
-
- // The new target is loaded from the {new.target} variable.
- VisitForValue(super->new_target_var());
-
- // Create node to perform the super call.
- const Operator* call =
- javascript()->CallConstruct(args->length() + 2, 0.0f, VectorSlotPair());
- Node* value = ProcessArguments(call, args->length() + 2);
- PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
- ast_context()->ProduceValue(expr, value);
-}
-
-
void AstGraphBuilder::VisitCallNew(CallNew* expr) {
VisitForValue(expr->expression());
@@ -2505,7 +1724,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
float const frequency = ComputeCallFrequency(expr->CallNewFeedbackSlot());
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
const Operator* call =
- javascript()->CallConstruct(args->length() + 2, frequency, feedback);
+ javascript()->Construct(args->length() + 2, frequency, feedback);
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
ast_context()->ProduceValue(expr, value);
@@ -2526,7 +1745,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
VisitForValues(args);
// Create node to perform the JS runtime call.
- const Operator* call = javascript()->CallFunction(args->length() + 2);
+ const Operator* call = javascript()->Call(args->length() + 2);
PrepareEagerCheckpoint(expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
@@ -2625,35 +1844,10 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
stack_depth = 2;
break;
}
- case NAMED_SUPER_PROPERTY: {
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- Node* home_object = environment()->Top();
- Node* receiver = environment()->Peek(1);
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- VectorSlotPair pair =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
- PrepareFrameState(old_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- stack_depth = 2;
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
- VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
- VisitForValue(property->key());
- Node* key = environment()->Top();
- Node* home_object = environment()->Peek(1);
- Node* receiver = environment()->Peek(2);
- VectorSlotPair pair =
- CreateVectorSlotPair(property->PropertyFeedbackSlot());
- old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
- PrepareFrameState(old_value, property->LoadId(),
- OutputFrameStateCombine::Push());
- stack_depth = 3;
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNREACHABLE();
break;
- }
}
// Convert old value into a number.
@@ -2708,24 +1902,10 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
OutputFrameStateCombine::Push());
break;
}
- case NAMED_SUPER_PROPERTY: {
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
- Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
- PrepareFrameState(store, expr->AssignmentId(),
- OutputFrameStateCombine::Push());
- break;
- }
- case KEYED_SUPER_PROPERTY: {
- Node* key = environment()->Pop();
- Node* home_object = environment()->Pop();
- Node* receiver = environment()->Pop();
- Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
- PrepareFrameState(store, expr->AssignmentId(),
- OutputFrameStateCombine::Push());
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNREACHABLE();
break;
- }
}
// Restore old value for postfix expressions.
@@ -2804,13 +1984,7 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
}
- CompareOperationHint hint;
- if (!type_hint_analysis_ ||
- !type_hint_analysis_->GetCompareOperationHint(
- expr->CompareOperationFeedbackId(), &hint)) {
- hint = CompareOperationHint::kAny;
- }
-
+ CompareOperationHint hint = CompareOperationHint::kAny;
const Operator* op;
switch (expr->op()) {
case Token::EQ:
@@ -2868,6 +2042,10 @@ void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
UNREACHABLE();
}
+void AstGraphBuilder::VisitGetIterator(GetIterator* expr) {
+ // GetIterator is supported only by going through Ignition first.
+ UNREACHABLE();
+}
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
Node* value = GetFunctionClosure();
@@ -2877,8 +2055,7 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
void AstGraphBuilder::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
- Node* value = BuildThrowUnsupportedSuperError(expr->id());
- ast_context()->ProduceValue(expr, value);
+ UNREACHABLE();
}
@@ -2898,17 +2075,16 @@ void AstGraphBuilder::VisitDeclarations(Declaration::List* declarations) {
AstVisitor<AstGraphBuilder>::VisitDeclarations(declarations);
if (globals()->empty()) return;
int array_index = 0;
- Handle<TypeFeedbackVector> feedback_vector(
- info()->closure()->feedback_vector());
+ Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector());
Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
static_cast<int>(globals()->size()), TENURED);
for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
int encoded_flags = info()->GetDeclareGlobalsFlags();
Node* flags = jsgraph()->Constant(encoded_flags);
- Node* pairs = jsgraph()->Constant(data);
+ Node* decls = jsgraph()->Constant(data);
Node* vector = jsgraph()->Constant(feedback_vector);
const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
- Node* call = NewNode(op, pairs, flags, vector);
+ Node* call = NewNode(op, decls, flags, vector);
PrepareFrameState(call, BailoutId::Declarations());
globals()->clear();
}
@@ -2920,20 +2096,12 @@ void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
}
-void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
- ContextScope scope(this, s, context);
- DCHECK(s->declarations()->is_empty());
- Visit(stmt);
-}
-
void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
LoopBuilder* loop,
BailoutId stack_check_id) {
ControlScopeForIteration scope(this, stmt, loop);
- if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
- Node* node = NewNode(javascript()->StackCheck());
- PrepareFrameState(node, stack_check_id);
- }
+ Node* node = NewNode(javascript()->StackCheck());
+ PrepareFrameState(node, stack_check_id);
Visit(stmt->body());
}
@@ -3063,9 +2231,7 @@ LanguageMode AstGraphBuilder::language_mode() const {
return current_scope()->language_mode();
}
-
-VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
- FeedbackVectorSlot slot) const {
+VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(FeedbackSlot slot) const {
return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
}
@@ -3074,50 +2240,10 @@ void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Visit(node->expression());
}
-
-namespace {
-
-// Limit of context chain length to which inline check is possible.
-const int kMaxCheckDepth = 30;
-
-// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
-const uint32_t kFullCheckRequired = -1;
-
-} // namespace
-
-
-uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
- DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
- uint32_t check_depths = 0;
- for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
- if (!s->NeedsContext()) continue;
- if (!s->calls_sloppy_eval()) continue;
- int depth = current_scope()->ContextChainLength(s);
- if (depth > kMaxCheckDepth) return kFullCheckRequired;
- check_depths |= 1 << depth;
- }
- return check_depths;
-}
-
-
-uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
- DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
- uint32_t check_depths = 0;
- for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
- if (!s->NeedsContext()) continue;
- if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
- int depth = current_scope()->ContextChainLength(s);
- if (depth > kMaxCheckDepth) return kFullCheckRequired;
- check_depths |= 1 << depth;
- if (s == variable->scope()) break;
- }
- return check_depths;
-}
-
-float AstGraphBuilder::ComputeCallFrequency(FeedbackVectorSlot slot) const {
+float AstGraphBuilder::ComputeCallFrequency(FeedbackSlot slot) const {
if (slot.IsInvalid()) return 0.0f;
- Handle<TypeFeedbackVector> feedback_vector(
- info()->closure()->feedback_vector(), isolate());
+ Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector(),
+ isolate());
CallICNexus nexus(feedback_vector, slot);
return nexus.ComputeCallFrequency() * invocation_frequency_;
}
@@ -3147,7 +2273,8 @@ Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
Variable* variable = scope->receiver();
DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
const Operator* op = javascript()->StoreContext(0, variable->index());
- NewNode(op, local_context, receiver);
+ Node* node = NewNode(op, receiver);
+ NodeProperties::ReplaceContextInput(node, local_context);
}
// Copy parameters into context if necessary.
@@ -3159,7 +2286,8 @@ Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
// Context variable (at bottom of the context chain).
DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
const Operator* op = javascript()->StoreContext(0, variable->index());
- NewNode(op, local_context, parameter);
+ Node* node = NewNode(op, parameter);
+ NodeProperties::ReplaceContextInput(node, local_context);
}
return local_context;
@@ -3171,7 +2299,8 @@ Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
// Allocate a new local context.
int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
- const Operator* op = javascript()->CreateFunctionContext(slot_count);
+ const Operator* op =
+ javascript()->CreateFunctionContext(slot_count, scope->scope_type());
Node* local_context = NewNode(op, GetFunctionClosure());
return local_context;
@@ -3224,52 +2353,6 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
return object;
}
-Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest) {
- if (rest == nullptr) return nullptr;
-
- // Allocate and initialize a new arguments object.
- CreateArgumentsType type = CreateArgumentsType::kRestParameter;
- const Operator* op = javascript()->CreateArguments(type);
- Node* object = NewNode(op, GetFunctionClosure());
- PrepareFrameState(object, BailoutId::None());
-
- // Assign the object to the {rest} variable. This should never lazy
- // deopt, so it is fine to send invalid bailout id.
- DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
- BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
- BailoutId::None());
- return object;
-}
-
-
-Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
- if (this_function_var == nullptr) return nullptr;
-
- // Retrieve the closure we were called with.
- Node* this_function = GetFunctionClosure();
-
- // Assign the object to the {.this_function} variable. This should never lazy
- // deopt, so it is fine to send invalid bailout id.
- BuildVariableAssignment(this_function_var, this_function, Token::INIT,
- VectorSlotPair(), BailoutId::None());
- return this_function;
-}
-
-
-Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
- if (new_target_var == nullptr) return nullptr;
-
- // Retrieve the new target we were called with.
- Node* object = GetNewTarget();
-
- // Assign the object to the {new.target} variable. This should never lazy
- // deopt, so it is fine to send invalid bailout id.
- BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
- BailoutId::None());
- return object;
-}
-
-
Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
Node* not_hole,
BailoutId bailout_id) {
@@ -3305,25 +2388,6 @@ Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
return environment()->Pop();
}
-
-Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
- BailoutId bailout_id) {
- IfBuilder prototype_check(this);
- Node* prototype_string =
- jsgraph()->Constant(isolate()->factory()->prototype_string());
- Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
- name, prototype_string);
- prototype_check.If(check);
- prototype_check.Then();
- Node* error = BuildThrowStaticPrototypeError(bailout_id);
- environment()->Push(error);
- prototype_check.Else();
- environment()->Push(name);
- prototype_check.End();
- return environment()->Pop();
-}
-
-
Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
BailoutId bailout_id,
const VectorSlotPair& feedback,
@@ -3363,7 +2427,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
info()->is_function_context_specializing();
const Operator* op =
javascript()->LoadContext(depth, variable->index(), immutable);
- Node* value = NewNode(op, current_context());
+ Node* value = NewNode(op);
// TODO(titzer): initialization checks are redundant for already
// initialized immutable context loads, but only specialization knows.
// Maybe specializer should be a parameter to the graph builder?
@@ -3373,17 +2437,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
}
return value;
}
- case VariableLocation::LOOKUP: {
- // Dynamic lookup of context variable (anywhere in the chain).
- Handle<String> name = variable->name();
- if (Node* node = TryLoadDynamicVariable(variable, name, bailout_id,
- feedback, combine, typeof_mode)) {
- return node;
- }
- Node* value = BuildDynamicLoad(name, typeof_mode);
- PrepareFrameState(value, bailout_id, combine);
- return value;
- }
+ case VariableLocation::LOOKUP:
case VariableLocation::MODULE:
UNREACHABLE();
}
@@ -3411,15 +2465,7 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
// Local var, const, or let variable or context variable.
return jsgraph()->BooleanConstant(variable->is_this());
}
- case VariableLocation::LOOKUP: {
- // Dynamic lookup of context variable (anywhere in the chain).
- Node* name = jsgraph()->Constant(variable->name());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
- Node* result = NewNode(op, name);
- PrepareFrameState(result, bailout_id, combine);
- return result;
- }
+ case VariableLocation::LOOKUP:
case VariableLocation::MODULE:
UNREACHABLE();
}
@@ -3498,7 +2544,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// Perform an initialization check for let declared variables.
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
- Node* current = NewNode(op, current_context());
+ Node* current = NewNode(op);
value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
} else if (mode == CONST && op == Token::INIT) {
// Perform an initialization check for const {this} variables.
@@ -3507,7 +2553,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
if (variable->is_this()) {
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
- Node* current = NewNode(op, current_context());
+ Node* current = NewNode(op);
value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
}
} else if (mode == CONST && op != Token::INIT &&
@@ -3524,22 +2570,16 @@ Node* AstGraphBuilder::BuildVariableAssignment(
if (variable->binding_needs_init()) {
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
- Node* current = NewNode(op, current_context());
+ Node* current = NewNode(op);
BuildHoleCheckThenThrow(current, variable, value, bailout_id);
}
// Assignment to const is exception in all modes.
return BuildThrowConstAssignError(bailout_id);
}
const Operator* op = javascript()->StoreContext(depth, variable->index());
- return NewNode(op, current_context(), value);
- }
- case VariableLocation::LOOKUP: {
- // Dynamic lookup of context variable (anywhere in the chain).
- Handle<Name> name = variable->name();
- Node* store = BuildDynamicStore(name, value);
- PrepareFrameState(store, bailout_id, combine);
- return store;
+ return NewNode(op, value);
}
+ case VariableLocation::LOOKUP:
case VariableLocation::MODULE:
UNREACHABLE();
}
@@ -3551,7 +2591,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
const VectorSlotPair& feedback) {
const Operator* op = javascript()->LoadProperty(feedback);
- Node* node = NewNode(op, object, key, GetFunctionClosure());
+ Node* node = NewNode(op, object, key);
return node;
}
@@ -3559,15 +2599,17 @@ Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
const VectorSlotPair& feedback) {
const Operator* op = javascript()->LoadNamed(name, feedback);
- Node* node = NewNode(op, object, GetFunctionClosure());
+ Node* node = NewNode(op, object);
return node;
}
Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
const VectorSlotPair& feedback) {
+ DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
+ language_mode());
const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
- Node* node = NewNode(op, object, key, value, GetFunctionClosure());
+ Node* node = NewNode(op, object, key, value);
return node;
}
@@ -3575,60 +2617,30 @@ Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
Node* value,
const VectorSlotPair& feedback) {
+ DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
+ language_mode());
const Operator* op =
javascript()->StoreNamed(language_mode(), name, feedback);
- Node* node = NewNode(op, object, value, GetFunctionClosure());
- return node;
-}
-
-
-Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
- Handle<Name> name,
- const VectorSlotPair& feedback) {
- Node* name_node = jsgraph()->Constant(name);
- const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
- Node* node = NewNode(op, receiver, home_object, name_node);
- return node;
-}
-
-
-Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
- Node* key,
- const VectorSlotPair& feedback) {
- const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
- Node* node = NewNode(op, receiver, home_object, key);
- return node;
-}
-
-
-Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
- Node* key, Node* value) {
- Runtime::FunctionId function_id = is_strict(language_mode())
- ? Runtime::kStoreKeyedToSuper_Strict
- : Runtime::kStoreKeyedToSuper_Sloppy;
- const Operator* op = javascript()->CallRuntime(function_id, 4);
- Node* node = NewNode(op, receiver, home_object, key, value);
+ Node* node = NewNode(op, object, value);
return node;
}
-
-Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
- Handle<Name> name, Node* value) {
- Node* name_node = jsgraph()->Constant(name);
- Runtime::FunctionId function_id = is_strict(language_mode())
- ? Runtime::kStoreToSuper_Strict
- : Runtime::kStoreToSuper_Sloppy;
- const Operator* op = javascript()->CallRuntime(function_id, 4);
- Node* node = NewNode(op, receiver, home_object, name_node, value);
+Node* AstGraphBuilder::BuildNamedStoreOwn(Node* object, Handle<Name> name,
+ Node* value,
+ const VectorSlotPair& feedback) {
+ DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
+ feedback.vector()->GetKind(feedback.slot()));
+ const Operator* op = javascript()->StoreNamedOwn(name, feedback);
+ Node* node = NewNode(op, object, value);
return node;
}
-
Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
const VectorSlotPair& feedback,
TypeofMode typeof_mode) {
+ DCHECK_EQ(feedback.vector()->GetTypeofMode(feedback.slot()), typeof_mode);
const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
- Node* node = NewNode(op, GetFunctionClosure());
+ Node* node = NewNode(op);
return node;
}
@@ -3637,33 +2649,10 @@ Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
const VectorSlotPair& feedback) {
const Operator* op =
javascript()->StoreGlobal(language_mode(), name, feedback);
- Node* node = NewNode(op, value, GetFunctionClosure());
- return node;
-}
-
-
-Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
- TypeofMode typeof_mode) {
- Node* name_node = jsgraph()->Constant(name);
- const Operator* op =
- javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
- ? Runtime::kLoadLookupSlot
- : Runtime::kLoadLookupSlotInsideTypeof);
- Node* node = NewNode(op, name_node);
- return node;
-}
-
-
-Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
- Node* name_node = jsgraph()->Constant(name);
- const Operator* op = javascript()->CallRuntime(
- is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
- : Runtime::kStoreLookupSlot_Sloppy);
- Node* node = NewNode(op, name_node, value);
+ Node* node = NewNode(op, value);
return node;
}
-
Node* AstGraphBuilder::BuildLoadGlobalObject() {
return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
}
@@ -3672,30 +2661,20 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() {
Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
const Operator* op =
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
- Node* native_context = NewNode(op, current_context());
- return NewNode(javascript()->LoadContext(0, index, true), native_context);
+ Node* native_context = NewNode(op);
+ Node* result = NewNode(javascript()->LoadContext(0, index, true));
+ NodeProperties::ReplaceContextInput(result, native_context);
+ return result;
}
Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
if (Node* node = TryFastToBoolean(input)) return node;
- ToBooleanHints hints;
- if (!type_hint_analysis_ ||
- !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
- hints = ToBooleanHint::kAny;
- }
+ ToBooleanHints hints = ToBooleanHint::kAny;
return NewNode(javascript()->ToBoolean(hints), input);
}
-Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
- if (Node* node = TryFastToName(input)) return node;
- Node* name = NewNode(javascript()->ToName(), input);
- PrepareFrameState(name, bailout_id, OutputFrameStateCombine::Push());
- return name;
-}
-
-
Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
Node* object = NewNode(javascript()->ToObject(), input);
PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
@@ -3750,28 +2729,6 @@ Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
}
-Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
- const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
- Node* call = NewNode(op);
- PrepareFrameState(call, bailout_id);
- Node* control = NewNode(common()->Throw(), call);
- UpdateControlDependencyToLeaveFunction(control);
- return call;
-}
-
-
-Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
- const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
- Node* call = NewNode(op);
- PrepareFrameState(call, bailout_id);
- Node* control = NewNode(common()->Throw(), call);
- UpdateControlDependencyToLeaveFunction(control);
- return call;
-}
-
-
Node* AstGraphBuilder::BuildReturn(Node* return_value) {
// Emit tracing call if requested to do so.
if (FLAG_trace) {
@@ -3796,44 +2753,40 @@ Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
TypeFeedbackId feedback_id) {
const Operator* js_op;
- BinaryOperationHint hint;
- if (!type_hint_analysis_ ||
- !type_hint_analysis_->GetBinaryOperationHint(feedback_id, &hint)) {
- hint = BinaryOperationHint::kAny;
- }
+ BinaryOperationHint hint = BinaryOperationHint::kAny;
switch (op) {
case Token::BIT_OR:
- js_op = javascript()->BitwiseOr(hint);
+ js_op = javascript()->BitwiseOr();
break;
case Token::BIT_AND:
- js_op = javascript()->BitwiseAnd(hint);
+ js_op = javascript()->BitwiseAnd();
break;
case Token::BIT_XOR:
- js_op = javascript()->BitwiseXor(hint);
+ js_op = javascript()->BitwiseXor();
break;
case Token::SHL:
- js_op = javascript()->ShiftLeft(hint);
+ js_op = javascript()->ShiftLeft();
break;
case Token::SAR:
- js_op = javascript()->ShiftRight(hint);
+ js_op = javascript()->ShiftRight();
break;
case Token::SHR:
- js_op = javascript()->ShiftRightLogical(hint);
+ js_op = javascript()->ShiftRightLogical();
break;
case Token::ADD:
js_op = javascript()->Add(hint);
break;
case Token::SUB:
- js_op = javascript()->Subtract(hint);
+ js_op = javascript()->Subtract();
break;
case Token::MUL:
- js_op = javascript()->Multiply(hint);
+ js_op = javascript()->Multiply();
break;
case Token::DIV:
- js_op = javascript()->Divide(hint);
+ js_op = javascript()->Divide();
break;
case Token::MOD:
- js_op = javascript()->Modulus(hint);
+ js_op = javascript()->Modulus();
break;
default:
UNREACHABLE();
@@ -3850,109 +2803,6 @@ Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
return nullptr;
}
-Node* AstGraphBuilder::TryLoadDynamicVariable(Variable* variable,
- Handle<String> name,
- BailoutId bailout_id,
- const VectorSlotPair& feedback,
- OutputFrameStateCombine combine,
- TypeofMode typeof_mode) {
- VariableMode mode = variable->mode();
-
- if (mode == DYNAMIC_GLOBAL) {
- uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
- if (bitset == kFullCheckRequired) return nullptr;
-
- // We are using two blocks to model fast and slow cases.
- BlockBuilder fast_block(this);
- BlockBuilder slow_block(this);
- environment()->Push(jsgraph()->TheHoleConstant());
- slow_block.BeginBlock();
- environment()->Pop();
- fast_block.BeginBlock();
-
- // Perform checks whether the fast mode applies, by looking for any
- // extension object which might shadow the optimistic declaration.
- for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
- if ((bitset & 1) == 0) continue;
- Node* load = NewNode(
- javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
- current_context());
- Node* check =
- NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load,
- jsgraph()->TheHoleConstant());
- fast_block.BreakUnless(check, BranchHint::kTrue);
- }
-
- // Fast case, because variable is not shadowed.
- if (Node* constant = TryLoadGlobalConstant(name)) {
- environment()->Push(constant);
- } else {
- // Perform global slot load.
- Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
- PrepareFrameState(fast, bailout_id, combine);
- environment()->Push(fast);
- }
- slow_block.Break();
- environment()->Pop();
- fast_block.EndBlock();
-
- // Slow case, because variable potentially shadowed. Perform dynamic lookup.
- Node* slow = BuildDynamicLoad(name, typeof_mode);
- PrepareFrameState(slow, bailout_id, combine);
- environment()->Push(slow);
- slow_block.EndBlock();
-
- return environment()->Pop();
- }
-
- if (mode == DYNAMIC_LOCAL) {
- uint32_t bitset = ComputeBitsetForDynamicContext(variable);
- if (bitset == kFullCheckRequired) return nullptr;
-
- // We are using two blocks to model fast and slow cases.
- BlockBuilder fast_block(this);
- BlockBuilder slow_block(this);
- environment()->Push(jsgraph()->TheHoleConstant());
- slow_block.BeginBlock();
- environment()->Pop();
- fast_block.BeginBlock();
-
- // Perform checks whether the fast mode applies, by looking for any
- // extension object which might shadow the optimistic declaration.
- for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
- if ((bitset & 1) == 0) continue;
- Node* load = NewNode(
- javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
- current_context());
- Node* check =
- NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load,
- jsgraph()->TheHoleConstant());
- fast_block.BreakUnless(check, BranchHint::kTrue);
- }
-
- // Fast case, because variable is not shadowed. Perform context slot load.
- Variable* local = variable->local_if_not_shadowed();
- DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
- Node* fast =
- BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode);
- environment()->Push(fast);
- slow_block.Break();
- environment()->Pop();
- fast_block.EndBlock();
-
- // Slow case, because variable potentially shadowed. Perform dynamic lookup.
- Node* slow = BuildDynamicLoad(name, typeof_mode);
- PrepareFrameState(slow, bailout_id, combine);
- environment()->Push(slow);
- slow_block.EndBlock();
-
- return environment()->Pop();
- }
-
- return nullptr;
-}
-
-
Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
switch (input->opcode()) {
case IrOpcode::kNumberConstant: {
@@ -3983,24 +2833,6 @@ Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
}
-Node* AstGraphBuilder::TryFastToName(Node* input) {
- switch (input->opcode()) {
- case IrOpcode::kHeapConstant: {
- Handle<HeapObject> object = HeapObjectMatcher(input).Value();
- if (object->IsName()) return input;
- break;
- }
- case IrOpcode::kJSToString:
- case IrOpcode::kJSToName:
- case IrOpcode::kJSTypeOf:
- return input;
- default:
- break;
- }
- return nullptr;
-}
-
-
bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
if (info()->osr_ast_id() == stmt->OsrEntryId()) {
DCHECK_EQ(-1, info()->osr_expr_stack_height());
@@ -4073,7 +2905,6 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
if (!has_context && !has_frame_state && !has_control && !has_effect) {
result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
} else {
- bool inside_try_scope = try_nesting_level_ > 0;
int input_count_with_deps = value_input_count;
if (has_context) ++input_count_with_deps;
if (has_frame_state) ++input_count_with_deps;
@@ -4107,18 +2938,6 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
if (result->op()->EffectOutputCount() > 0) {
environment_->UpdateEffectDependency(result);
}
- // Add implicit exception continuation for throwing nodes.
- if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
- // Copy the environment for the success continuation.
- Environment* success_env = environment()->CopyForConditional();
- const Operator* op = common()->IfException();
- Node* effect = environment()->GetEffectDependency();
- Node* on_exception = graph()->NewNode(op, effect, result);
- environment_->UpdateControlDependency(on_exception);
- environment_->UpdateEffectDependency(on_exception);
- execution_control()->ThrowValue(on_exception);
- set_environment(success_env);
- }
// Add implicit success continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow)) {
const Operator* op = common()->IfSuccess();
@@ -4244,8 +3063,7 @@ void AstGraphBuilder::Environment::PrepareForOsrEntry() {
Node* osr_context = effect = contexts()->back();
int last = static_cast<int>(contexts()->size() - 1);
for (int i = last - 1; i >= 0; i--) {
- osr_context = effect =
- graph->NewNode(load_op, osr_context, osr_context, effect);
+ osr_context = effect = graph->NewNode(load_op, osr_context, effect);
contexts()->at(i) = osr_context;
}
UpdateEffectDependency(effect);
@@ -4364,10 +3182,9 @@ Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
AstGraphBuilderWithPositions::AstGraphBuilderWithPositions(
Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
- TypeHintAnalysis* type_hint_analysis, SourcePositionTable* source_positions,
- int inlining_id)
+ SourcePositionTable* source_positions, int inlining_id)
: AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
- loop_assignment, type_hint_analysis),
+ loop_assignment),
source_positions_(source_positions),
start_position_(info->shared_info()->start_position(), inlining_id) {}