diff options
Diffstat (limited to 'src/compiler/ast-graph-builder.cc')
-rw-r--r-- | src/compiler/ast-graph-builder.cc | 1579 |
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) {} |