blob: da8b62607c6181f8c559e5fc816aac84f4500c59 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/ast-graph-builder.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/compiler/ast-loop-assignment-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/control-builders.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/linkage.h"
12#include "src/compiler/liveness-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/machine-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/compiler/node-matchers.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015#include "src/compiler/node-properties.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/compiler/operator-properties.h"
17#include "src/compiler/state-values-utils.h"
18#include "src/compiler/type-hint-analyzer.h"
19#include "src/parsing/parser.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020
21namespace v8 {
22namespace internal {
23namespace compiler {
24
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025
26// Each expression in the AST is evaluated in a specific context. This context
27// decides how the evaluation result is passed up the visitor.
28class AstGraphBuilder::AstContext BASE_EMBEDDED {
29 public:
30 bool IsEffect() const { return kind_ == Expression::kEffect; }
31 bool IsValue() const { return kind_ == Expression::kValue; }
32 bool IsTest() const { return kind_ == Expression::kTest; }
33
34 // Determines how to combine the frame state with the value
35 // that is about to be plugged into this AstContext.
36 OutputFrameStateCombine GetStateCombine() {
37 return IsEffect() ? OutputFrameStateCombine::Ignore()
38 : OutputFrameStateCombine::Push();
39 }
40
41 // Plug a node into this expression context. Call this function in tail
42 // position in the Visit functions for expressions.
43 virtual void ProduceValue(Node* value) = 0;
44
45 // Unplugs a node from this expression context. Call this to retrieve the
46 // result of another Visit function that already plugged the context.
47 virtual Node* ConsumeValue() = 0;
48
49 // Shortcut for "context->ProduceValue(context->ConsumeValue())".
50 void ReplaceValue() { ProduceValue(ConsumeValue()); }
51
52 protected:
53 AstContext(AstGraphBuilder* owner, Expression::Context kind);
54 virtual ~AstContext();
55
56 AstGraphBuilder* owner() const { return owner_; }
57 Environment* environment() const { return owner_->environment(); }
58
59// We want to be able to assert, in a context-specific way, that the stack
60// height makes sense when the context is filled.
61#ifdef DEBUG
62 int original_height_;
63#endif
64
65 private:
66 Expression::Context kind_;
67 AstGraphBuilder* owner_;
68 AstContext* outer_;
69};
70
71
72// Context to evaluate expression for its side effects only.
73class AstGraphBuilder::AstEffectContext final : public AstContext {
74 public:
75 explicit AstEffectContext(AstGraphBuilder* owner)
76 : AstContext(owner, Expression::kEffect) {}
77 ~AstEffectContext() final;
78 void ProduceValue(Node* value) final;
79 Node* ConsumeValue() final;
80};
81
82
83// Context to evaluate expression for its value (and side effects).
84class AstGraphBuilder::AstValueContext final : public AstContext {
85 public:
86 explicit AstValueContext(AstGraphBuilder* owner)
87 : AstContext(owner, Expression::kValue) {}
88 ~AstValueContext() final;
89 void ProduceValue(Node* value) final;
90 Node* ConsumeValue() final;
91};
92
93
94// Context to evaluate expression for a condition value (and side effects).
95class AstGraphBuilder::AstTestContext final : public AstContext {
96 public:
97 AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
98 : AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
99 ~AstTestContext() final;
100 void ProduceValue(Node* value) final;
101 Node* ConsumeValue() final;
102
103 private:
104 TypeFeedbackId const feedback_id_;
105};
106
107
108// Scoped class tracking context objects created by the visitor. Represents
109// mutations of the context chain within the function body and allows to
110// change the current {scope} and {context} during visitation.
111class AstGraphBuilder::ContextScope BASE_EMBEDDED {
112 public:
113 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
114 : builder_(builder),
115 outer_(builder->execution_context()),
116 scope_(scope),
117 depth_(builder_->environment()->context_chain_length()) {
118 builder_->environment()->PushContext(context); // Push.
119 builder_->set_execution_context(this);
120 }
121
122 ~ContextScope() {
123 builder_->set_execution_context(outer_); // Pop.
124 builder_->environment()->PopContext();
125 CHECK_EQ(depth_, builder_->environment()->context_chain_length());
126 }
127
128 // Current scope during visitation.
129 Scope* scope() const { return scope_; }
130
131 private:
132 AstGraphBuilder* builder_;
133 ContextScope* outer_;
134 Scope* scope_;
135 int depth_;
136};
137
138
139// Scoped class tracking control statements entered by the visitor. There are
140// different types of statements participating in this stack to properly track
141// local as well as non-local control flow:
142// - IterationStatement : Allows proper 'break' and 'continue' behavior.
143// - BreakableStatement : Allows 'break' from block and switch statements.
144// - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges.
145// - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
146class AstGraphBuilder::ControlScope BASE_EMBEDDED {
147 public:
148 explicit ControlScope(AstGraphBuilder* builder)
149 : builder_(builder),
150 outer_(builder->execution_control()),
151 context_length_(builder->environment()->context_chain_length()),
152 stack_height_(builder->environment()->stack_height()) {
153 builder_->set_execution_control(this); // Push.
154 }
155
156 virtual ~ControlScope() {
157 builder_->set_execution_control(outer_); // Pop.
158 }
159
160 // Either 'break' or 'continue' to the target statement.
161 void BreakTo(BreakableStatement* target);
162 void ContinueTo(BreakableStatement* target);
163
164 // Either 'return' or 'throw' the given value.
165 void ReturnValue(Node* return_value);
166 void ThrowValue(Node* exception_value);
167
168 class DeferredCommands;
169
170 protected:
171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
172
173 // Performs one of the above commands on this stack of control scopes. This
174 // walks through the stack giving each scope a chance to execute or defer the
175 // given command by overriding the {Execute} method appropriately. Note that
176 // this also drops extra operands from the environment for each skipped scope.
177 void PerformCommand(Command cmd, Statement* target, Node* value);
178
179 // Interface to execute a given command in this scope. Returning {true} here
180 // indicates successful execution whereas {false} requests to skip scope.
181 virtual bool Execute(Command cmd, Statement* target, Node* value) {
182 // For function-level control.
183 switch (cmd) {
184 case CMD_THROW:
185 builder()->BuildThrow(value);
186 return true;
187 case CMD_RETURN:
188 builder()->BuildReturn(value);
189 return true;
190 case CMD_BREAK:
191 case CMD_CONTINUE:
192 break;
193 }
194 return false;
195 }
196
197 Environment* environment() { return builder_->environment(); }
198 AstGraphBuilder* builder() const { return builder_; }
199 int context_length() const { return context_length_; }
200 int stack_height() const { return stack_height_; }
201
202 private:
203 AstGraphBuilder* builder_;
204 ControlScope* outer_;
205 int context_length_;
206 int stack_height_;
207};
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209// Helper class for a try-finally control scope. It can record intercepted
210// control-flow commands that cause entry into a finally-block, and re-apply
211// them after again leaving that block. Special tokens are used to identify
212// paths going through the finally-block to dispatch after leaving the block.
213class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
214 public:
215 explicit DeferredCommands(AstGraphBuilder* owner)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 : owner_(owner),
217 deferred_(owner->local_zone()),
218 return_token_(nullptr),
219 throw_token_(nullptr) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220
221 // One recorded control-flow command.
222 struct Entry {
223 Command command; // The command type being applied on this path.
224 Statement* statement; // The target statement for the command or {nullptr}.
225 Node* token; // A token identifying this particular path.
226 };
227
228 // Records a control-flow command while entering the finally-block. This also
229 // generates a new dispatch token that identifies one particular path.
230 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231 Node* token = nullptr;
232 switch (cmd) {
233 case CMD_BREAK:
234 case CMD_CONTINUE:
235 token = NewPathToken(dispenser_.GetBreakContinueToken());
236 break;
237 case CMD_THROW:
238 if (throw_token_) return throw_token_;
239 token = NewPathToken(TokenDispenserForFinally::kThrowToken);
240 throw_token_ = token;
241 break;
242 case CMD_RETURN:
243 if (return_token_) return return_token_;
244 token = NewPathToken(TokenDispenserForFinally::kReturnToken);
245 return_token_ = token;
246 break;
247 }
248 DCHECK_NOT_NULL(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 deferred_.push_back({cmd, stmt, token});
250 return token;
251 }
252
253 // Returns the dispatch token to be used to identify the implicit fall-through
254 // path at the end of a try-block into the corresponding finally-block.
255 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
256
257 // Applies all recorded control-flow commands after the finally-block again.
258 // This generates a dynamic dispatch on the token from the entry point.
259 void ApplyDeferredCommands(Node* token, Node* value) {
260 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
261 dispatch.BeginSwitch();
262 for (size_t i = 0; i < deferred_.size(); ++i) {
263 Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
264 dispatch.BeginLabel(static_cast<int>(i), condition);
265 dispatch.EndLabel();
266 }
267 for (size_t i = 0; i < deferred_.size(); ++i) {
268 dispatch.BeginCase(static_cast<int>(i));
269 owner_->execution_control()->PerformCommand(
270 deferred_[i].command, deferred_[i].statement, value);
271 dispatch.EndCase();
272 }
273 dispatch.EndSwitch();
274 }
275
276 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100277 Node* NewPathToken(int token_id) {
278 return owner_->jsgraph()->Constant(token_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 }
280 Node* NewPathTokenForImplicitFallThrough() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 }
283 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
284 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
285 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
286 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
287 }
288
289 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 TokenDispenserForFinally dispenser_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 AstGraphBuilder* owner_;
292 ZoneVector<Entry> deferred_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 Node* return_token_;
294 Node* throw_token_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295};
296
297
298// Control scope implementation for a BreakableStatement.
299class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
300 public:
301 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
302 ControlBuilder* control)
303 : ControlScope(owner), target_(target), control_(control) {}
304
305 protected:
306 bool Execute(Command cmd, Statement* target, Node* value) override {
307 if (target != target_) return false; // We are not the command target.
308 switch (cmd) {
309 case CMD_BREAK:
310 control_->Break();
311 return true;
312 case CMD_CONTINUE:
313 case CMD_THROW:
314 case CMD_RETURN:
315 break;
316 }
317 return false;
318 }
319
320 private:
321 BreakableStatement* target_;
322 ControlBuilder* control_;
323};
324
325
326// Control scope implementation for an IterationStatement.
327class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
328 public:
329 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
330 LoopBuilder* control)
331 : ControlScope(owner), target_(target), control_(control) {}
332
333 protected:
334 bool Execute(Command cmd, Statement* target, Node* value) override {
335 if (target != target_) return false; // We are not the command target.
336 switch (cmd) {
337 case CMD_BREAK:
338 control_->Break();
339 return true;
340 case CMD_CONTINUE:
341 control_->Continue();
342 return true;
343 case CMD_THROW:
344 case CMD_RETURN:
345 break;
346 }
347 return false;
348 }
349
350 private:
351 BreakableStatement* target_;
352 LoopBuilder* control_;
353};
354
355
356// Control scope implementation for a TryCatchStatement.
357class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
358 public:
359 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
360 : ControlScope(owner), control_(control) {
361 builder()->try_nesting_level_++; // Increment nesting.
362 builder()->try_catch_nesting_level_++;
363 }
364 ~ControlScopeForCatch() {
365 builder()->try_nesting_level_--; // Decrement nesting.
366 builder()->try_catch_nesting_level_--;
367 }
368
369 protected:
370 bool Execute(Command cmd, Statement* target, Node* value) override {
371 switch (cmd) {
372 case CMD_THROW:
373 control_->Throw(value);
374 return true;
375 case CMD_BREAK:
376 case CMD_CONTINUE:
377 case CMD_RETURN:
378 break;
379 }
380 return false;
381 }
382
383 private:
384 TryCatchBuilder* control_;
385};
386
387
388// Control scope implementation for a TryFinallyStatement.
389class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
390 public:
391 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
392 TryFinallyBuilder* control)
393 : ControlScope(owner), commands_(commands), control_(control) {
394 builder()->try_nesting_level_++; // Increment nesting.
395 }
396 ~ControlScopeForFinally() {
397 builder()->try_nesting_level_--; // Decrement nesting.
398 }
399
400 protected:
401 bool Execute(Command cmd, Statement* target, Node* value) override {
402 Node* token = commands_->RecordCommand(cmd, target, value);
403 control_->LeaveTry(token, value);
404 return true;
405 }
406
407 private:
408 DeferredCommands* commands_;
409 TryFinallyBuilder* control_;
410};
411
412
413// Helper for generating before and after frame states.
414class AstGraphBuilder::FrameStateBeforeAndAfter {
415 public:
416 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before)
417 : builder_(builder), frame_state_before_(nullptr) {
418 frame_state_before_ = id_before == BailoutId::None()
419 ? builder_->jsgraph()->EmptyFrameState()
420 : builder_->environment()->Checkpoint(id_before);
421 }
422
423 void AddToNode(
424 Node* node, BailoutId id_after,
425 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) {
426 int count = OperatorProperties::GetFrameStateInputCount(node->op());
427 DCHECK_LE(count, 2);
428
429 if (count >= 1) {
430 // Add the frame state for after the operation.
431 DCHECK_EQ(IrOpcode::kDead,
432 NodeProperties::GetFrameStateInput(node, 0)->opcode());
433
Ben Murdoch097c5b22016-05-18 11:27:45 +0100434 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 Node* frame_state_after =
437 id_after == BailoutId::None()
438 ? builder_->jsgraph()->EmptyFrameState()
Ben Murdoch097c5b22016-05-18 11:27:45 +0100439 : builder_->environment()->Checkpoint(id_after, combine,
440 node_has_exception);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441
442 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
443 }
444
445 if (count >= 2) {
446 // Add the frame state for before the operation.
447 DCHECK_EQ(IrOpcode::kDead,
448 NodeProperties::GetFrameStateInput(node, 1)->opcode());
449 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
450 }
451 }
452
453 private:
454 AstGraphBuilder* builder_;
455 Node* frame_state_before_;
456};
457
458
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
461 TypeHintAnalysis* type_hint_analysis)
462 : isolate_(info->isolate()),
463 local_zone_(local_zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 info_(info),
465 jsgraph_(jsgraph),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 environment_(nullptr),
467 ast_context_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 globals_(0, local_zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 execution_control_(nullptr),
470 execution_context_(nullptr),
471 try_catch_nesting_level_(0),
472 try_nesting_level_(0),
473 input_buffer_size_(0),
474 input_buffer_(nullptr),
475 exit_controls_(local_zone),
476 loop_assignment_analysis_(loop),
477 type_hint_analysis_(type_hint_analysis),
478 state_values_cache_(jsgraph),
479 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
480 local_zone),
481 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
482 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100483 info->scope()->num_stack_slots(), info->shared_info())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 InitializeAstVisitor(info->isolate());
485}
486
487
488Node* AstGraphBuilder::GetFunctionClosureForContext() {
489 Scope* closure_scope = current_scope()->ClosureScope();
490 if (closure_scope->is_script_scope() ||
491 closure_scope->is_module_scope()) {
492 // Contexts nested in the native context have a canonical empty function as
493 // their closure, not the anonymous closure containing the global code.
494 return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
Ben Murdochc5610432016-08-08 18:44:38 +0100495 } else if (closure_scope->is_eval_scope()) {
496 // Contexts nested inside eval code have the same closure as the context
497 // calling eval, not the anonymous closure containing the eval code.
498 const Operator* op =
499 javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
500 return NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501 } else {
502 DCHECK(closure_scope->is_function_scope());
503 return GetFunctionClosure();
504 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505}
506
507
508Node* AstGraphBuilder::GetFunctionClosure() {
509 if (!function_closure_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 int index = Linkage::kJSCallClosureParamIndex;
511 const Operator* op = common()->Parameter(index, "%closure");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 Node* node = NewNode(op, graph()->start());
513 function_closure_.set(node);
514 }
515 return function_closure_.get();
516}
517
518
519Node* AstGraphBuilder::GetFunctionContext() {
520 if (!function_context_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 int params = info()->num_parameters_including_this();
522 int index = Linkage::GetJSCallContextParamIndex(params);
523 const Operator* op = common()->Parameter(index, "%context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524 Node* node = NewNode(op, graph()->start());
525 function_context_.set(node);
526 }
527 return function_context_.get();
528}
529
530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531Node* AstGraphBuilder::GetNewTarget() {
532 if (!new_target_.is_set()) {
533 int params = info()->num_parameters_including_this();
534 int index = Linkage::GetJSCallNewTargetParamIndex(params);
535 const Operator* op = common()->Parameter(index, "%new.target");
536 Node* node = NewNode(op, graph()->start());
537 new_target_.set(node);
538 }
539 return new_target_.get();
540}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542
543bool AstGraphBuilder::CreateGraph(bool stack_check) {
544 Scope* scope = info()->scope();
545 DCHECK_NOT_NULL(graph());
546
547 // Set up the basic structure of the graph. Outputs for {Start} are the formal
548 // parameters (including the receiver) plus new target, number of arguments,
549 // context and closure.
550 int actual_parameter_count = info()->num_parameters_including_this() + 4;
551 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552
553 // Initialize the top-level environment.
554 Environment env(this, scope, graph()->start());
555 set_environment(&env);
556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 if (info()->is_osr()) {
558 // Use OSR normal entry as the start of the top-level environment.
559 // It will be replaced with {Dead} after typing and optimizations.
560 NewNode(common()->OsrNormalEntry());
561 }
562
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400563 // Initialize the incoming context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 ContextScope incoming(this, scope, GetFunctionContext());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 // Initialize control scope.
567 ControlScope control(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
570 // not {the_hole}, because for derived classes {this} has a TDZ and the
571 // JSConstructStubForDerived magically passes {the_hole} as a receiver.
572 if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
573 env.RawParameterBind(0, jsgraph()->TheHoleConstant());
574 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 // Build local context only if there are context allocated variables.
Ben Murdochc5610432016-08-08 18:44:38 +0100577 if (scope->num_heap_slots() > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 // Push a new inner context scope for the current activation.
579 Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
580 ContextScope top_context(this, scope, inner_context);
581 CreateGraphBody(stack_check);
582 } else {
583 // Simply use the outer function context in building the graph.
584 CreateGraphBody(stack_check);
585 }
586
587 // Finish the basic structure of the graph.
588 DCHECK_NE(0u, exit_controls_.size());
589 int const input_count = static_cast<int>(exit_controls_.size());
590 Node** const inputs = &exit_controls_.front();
591 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
592 graph()->SetEnd(end);
593
594 // Compute local variable liveness information and use it to relax
595 // frame states.
596 ClearNonLiveSlotsInFrameStates();
597
598 // Failures indicated by stack overflow.
599 return !HasStackOverflow();
600}
601
602
603void AstGraphBuilder::CreateGraphBody(bool stack_check) {
604 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605
606 // Build the arguments object if it is used.
607 BuildArgumentsObject(scope->arguments());
608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 // Build rest arguments array if it is used.
610 int rest_index;
611 Variable* rest_parameter = scope->rest_parameter(&rest_index);
612 BuildRestArgumentsArray(rest_parameter, rest_index);
613
614 // Build assignment to {.this_function} variable if it is used.
615 BuildThisFunctionVariable(scope->this_function_var());
616
617 // Build assignment to {new.target} variable if it is used.
618 BuildNewTargetVariable(scope->new_target_var());
619
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 // Emit tracing call if requested to do so.
621 if (FLAG_trace) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100622 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 }
624
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 // Visit declarations within the function scope.
626 VisitDeclarations(scope->declarations());
627
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400628 // Build a stack-check before the body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 if (stack_check) {
630 Node* node = NewNode(javascript()->StackCheck());
631 PrepareFrameState(node, BailoutId::FunctionEntry());
632 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633
634 // Visit statements in the function body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 VisitStatements(info()->literal()->body());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 // Return 'undefined' in case we can fall off the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 BuildReturn(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639}
640
641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
643 if (!FLAG_analyze_environment_liveness ||
644 !info()->is_deoptimization_enabled()) {
645 return;
646 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 NonLiveFrameStateSlotReplacer replacer(
Ben Murdochda12d292016-06-02 14:46:10 +0100649 &state_values_cache_, jsgraph()->OptimizedOutConstant(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650 liveness_analyzer()->local_count(), local_zone());
651 Variable* arguments = info()->scope()->arguments();
652 if (arguments != nullptr && arguments->IsStackAllocated()) {
653 replacer.MarkPermanentlyLive(arguments->index());
654 }
655 liveness_analyzer()->Run(&replacer);
656 if (FLAG_trace_environment_liveness) {
657 OFStream os(stdout);
658 liveness_analyzer()->Print(os);
659 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660}
661
662
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663// Gets the bailout id just before reading a variable proxy, but only for
664// unallocated variables.
665static BailoutId BeforeId(VariableProxy* proxy) {
666 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
667 : BailoutId::None();
668}
669
670
671static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
672#if DEBUG
673 const AstRawString* name = scope->parameter(index)->raw_name();
674 if (name && name->length() > 0) {
675 char* data = zone->NewArray<char>(name->length() + 1);
676 data[name->length()] = 0;
677 memcpy(data, name->raw_data(), name->length());
678 return data;
679 }
680#endif
681 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682}
683
684
685AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
686 Scope* scope,
687 Node* control_dependency)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000688 : builder_(builder),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 parameters_count_(scope->num_parameters() + 1),
690 locals_count_(scope->num_stack_slots()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 liveness_block_(IsLivenessAnalysisEnabled()
692 ? builder_->liveness_analyzer()->NewBlock()
693 : nullptr),
694 values_(builder_->local_zone()),
695 contexts_(builder_->local_zone()),
696 control_dependency_(control_dependency),
697 effect_dependency_(control_dependency),
698 parameters_node_(nullptr),
699 locals_node_(nullptr),
700 stack_node_(nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
702
703 // Bind the receiver variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 int param_num = 0;
705 if (builder->info()->is_this_defined()) {
706 const Operator* op = common()->Parameter(param_num++, "%this");
707 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
708 values()->push_back(receiver);
709 } else {
710 values()->push_back(builder->jsgraph()->UndefinedConstant());
711 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712
713 // Bind all parameter variables. The parameter indices are shifted by 1
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 // (receiver is variable index -1 but {Parameter} node index 0 and located at
715 // index 0 in the environment).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 for (int i = 0; i < scope->num_parameters(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
718 const Operator* op = common()->Parameter(param_num++, debug_name);
719 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 values()->push_back(parameter);
721 }
722
723 // Bind all local variables to undefined.
724 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
725 values()->insert(values()->end(), locals_count(), undefined_constant);
726}
727
728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
730 LivenessAnalyzerBlock* liveness_block)
731 : builder_(copy->builder_),
732 parameters_count_(copy->parameters_count_),
733 locals_count_(copy->locals_count_),
734 liveness_block_(liveness_block),
735 values_(copy->zone()),
736 contexts_(copy->zone()),
737 control_dependency_(copy->control_dependency_),
738 effect_dependency_(copy->effect_dependency_),
739 parameters_node_(copy->parameters_node_),
740 locals_node_(copy->locals_node_),
741 stack_node_(copy->stack_node_) {
742 const size_t kStackEstimate = 7; // optimum from experimentation!
743 values_.reserve(copy->values_.size() + kStackEstimate);
744 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
745 contexts_.reserve(copy->contexts_.size());
746 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
747 copy->contexts_.end());
748}
749
750
751void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
752 DCHECK(variable->IsStackAllocated());
753 if (variable->IsParameter()) {
754 // The parameter indices are shifted by 1 (receiver is variable
755 // index -1 but located at index 0 in the environment).
756 values()->at(variable->index() + 1) = node;
757 } else {
758 DCHECK(variable->IsStackLocal());
759 values()->at(variable->index() + parameters_count_) = node;
760 DCHECK(IsLivenessBlockConsistent());
761 if (liveness_block() != nullptr) {
762 liveness_block()->Bind(variable->index());
763 }
764 }
765}
766
767
768Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
769 DCHECK(variable->IsStackAllocated());
770 if (variable->IsParameter()) {
771 // The parameter indices are shifted by 1 (receiver is variable
772 // index -1 but located at index 0 in the environment).
773 return values()->at(variable->index() + 1);
774 } else {
775 DCHECK(variable->IsStackLocal());
776 DCHECK(IsLivenessBlockConsistent());
777 if (liveness_block() != nullptr) {
778 liveness_block()->Lookup(variable->index());
779 }
780 return values()->at(variable->index() + parameters_count_);
781 }
782}
783
784
785void AstGraphBuilder::Environment::MarkAllLocalsLive() {
786 DCHECK(IsLivenessBlockConsistent());
787 if (liveness_block() != nullptr) {
788 for (int i = 0; i < locals_count_; i++) {
789 liveness_block()->Lookup(i);
790 }
791 }
792}
793
794
795void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
796 DCHECK_LT(index, parameters_count());
797 values()->at(index) = node;
798}
799
800
801Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
802 DCHECK_LT(index, parameters_count());
803 return values()->at(index);
804}
805
806
807AstGraphBuilder::Environment*
808AstGraphBuilder::Environment::CopyForConditional() {
809 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
810 if (liveness_block() != nullptr) {
811 copy_liveness_block =
812 builder_->liveness_analyzer()->NewBlock(liveness_block());
813 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
814 }
815 return new (zone()) Environment(this, copy_liveness_block);
816}
817
818
819AstGraphBuilder::Environment*
820AstGraphBuilder::Environment::CopyAsUnreachable() {
821 Environment* env = new (zone()) Environment(this, nullptr);
822 env->MarkAsUnreachable();
823 return env;
824}
825
826
827AstGraphBuilder::Environment*
828AstGraphBuilder::Environment::CopyAndShareLiveness() {
829 if (liveness_block() != nullptr) {
830 // Finish the current liveness block before copying.
831 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
832 }
833 Environment* env = new (zone()) Environment(this, liveness_block());
834 return env;
835}
836
837
838AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
839 BitVector* assigned, bool is_osr) {
840 PrepareForLoop(assigned, is_osr);
841 return CopyAndShareLiveness();
842}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843
844
845void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
846 int offset, int count) {
847 bool should_update = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
849 if (*state_values == nullptr || (*state_values)->InputCount() != count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 should_update = true;
851 } else {
852 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
853 for (int i = 0; i < count; i++) {
854 if ((*state_values)->InputAt(i) != env_values[i]) {
855 should_update = true;
856 break;
857 }
858 }
859 }
860 if (should_update) {
861 const Operator* op = common()->StateValues(count);
862 (*state_values) = graph()->NewNode(op, count, env_values);
863 }
864}
865
866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
868 Node** state_values, int offset, int count) {
869 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
870 *state_values = builder_->state_values_cache_.GetNodeForValues(
871 env_values, static_cast<size_t>(count));
872}
873
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
875 OutputFrameStateCombine combine,
876 bool owner_has_exception) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 if (!builder()->info()->is_deoptimization_enabled()) {
878 return builder()->jsgraph()->EmptyFrameState();
879 }
880
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 UpdateStateValues(&parameters_node_, 0, parameters_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
884 stack_height());
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 const Operator* op = common()->FrameState(
887 ast_id, combine, builder()->frame_state_function_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
890 stack_node_, builder()->current_context(),
891 builder()->GetFunctionClosure(),
892 builder()->graph()->start());
893
894 DCHECK(IsLivenessBlockConsistent());
895 if (liveness_block() != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100896 // If the owning node has an exception, register the checkpoint to the
897 // predecessor so that the checkpoint is used for both the normal and the
898 // exceptional paths. Yes, this is a terrible hack and we might want
899 // to use an explicit frame state for the exceptional path.
900 if (owner_has_exception) {
901 liveness_block()->GetPredecessor()->Checkpoint(result);
902 } else {
903 liveness_block()->Checkpoint(result);
904 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000905 }
906 return result;
907}
908
909
910bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
911 return FLAG_analyze_environment_liveness &&
912 builder()->info()->is_deoptimization_enabled();
913}
914
915
916bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
917 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
918 (liveness_block() == nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919}
920
921
922AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
923 Expression::Context kind)
924 : kind_(kind), owner_(own), outer_(own->ast_context()) {
925 owner()->set_ast_context(this); // Push.
926#ifdef DEBUG
927 original_height_ = environment()->stack_height();
928#endif
929}
930
931
932AstGraphBuilder::AstContext::~AstContext() {
933 owner()->set_ast_context(outer_); // Pop.
934}
935
936
937AstGraphBuilder::AstEffectContext::~AstEffectContext() {
938 DCHECK(environment()->stack_height() == original_height_);
939}
940
941
942AstGraphBuilder::AstValueContext::~AstValueContext() {
943 DCHECK(environment()->stack_height() == original_height_ + 1);
944}
945
946
947AstGraphBuilder::AstTestContext::~AstTestContext() {
948 DCHECK(environment()->stack_height() == original_height_ + 1);
949}
950
951
952void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
953 // The value is ignored.
954}
955
956
957void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
958 environment()->Push(value);
959}
960
961
962void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964}
965
966
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968
969
970Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
971 return environment()->Pop();
972}
973
974
975Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
976 return environment()->Pop();
977}
978
979
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980Scope* AstGraphBuilder::current_scope() const {
981 return execution_context_->scope();
982}
983
984
985Node* AstGraphBuilder::current_context() const {
986 return environment()->Context();
987}
988
989
990void AstGraphBuilder::ControlScope::PerformCommand(Command command,
991 Statement* target,
992 Node* value) {
993 Environment* env = environment()->CopyAsUnreachable();
994 ControlScope* current = this;
995 while (current != nullptr) {
996 environment()->TrimStack(current->stack_height());
997 environment()->TrimContextChain(current->context_length());
998 if (current->Execute(command, target, value)) break;
999 current = current->outer_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 builder()->set_environment(env);
1002 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003}
1004
1005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
1007 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008}
1009
1010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
1012 PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
1013}
1014
1015
1016void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
1017 PerformCommand(CMD_RETURN, nullptr, return_value);
1018}
1019
1020
1021void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
1022 PerformCommand(CMD_THROW, nullptr, exception_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023}
1024
1025
1026void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 if (expr == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 return environment()->Push(jsgraph()->NullConstant());
1029 }
1030 VisitForValue(expr);
1031}
1032
1033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1035 if (expr == nullptr) {
1036 return environment()->Push(jsgraph()->TheHoleConstant());
1037 }
1038 VisitForValue(expr);
1039}
1040
1041
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1043 for (int i = 0; i < exprs->length(); ++i) {
1044 VisitForValue(exprs->at(i));
1045 }
1046}
1047
1048
1049void AstGraphBuilder::VisitForValue(Expression* expr) {
1050 AstValueContext for_value(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001051 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 } else {
1054 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 }
1056}
1057
1058
1059void AstGraphBuilder::VisitForEffect(Expression* expr) {
1060 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001061 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001063 } else {
1064 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 }
1066}
1067
1068
1069void AstGraphBuilder::VisitForTest(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 AstTestContext for_condition(this, expr->test_id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001071 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073 } else {
1074 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1075 }
1076}
1077
1078
1079void AstGraphBuilder::Visit(Expression* expr) {
1080 // Reuses enclosing AstContext.
1081 if (!CheckStackOverflow()) {
1082 expr->Accept(this);
1083 } else {
1084 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 }
1086}
1087
1088
1089void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1090 Variable* variable = decl->proxy()->var();
1091 VariableMode mode = decl->mode();
Ben Murdochc5610432016-08-08 18:44:38 +01001092 bool hole_init = mode == CONST || mode == LET;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 case VariableLocation::GLOBAL:
Ben Murdochc5610432016-08-08 18:44:38 +01001095 case VariableLocation::UNALLOCATED:
1096 DCHECK(!variable->binding_needs_init());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001097 globals()->push_back(variable->name());
Ben Murdochc5610432016-08-08 18:44:38 +01001098 globals()->push_back(isolate()->factory()->undefined_value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100 case VariableLocation::PARAMETER:
1101 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 if (hole_init) {
1103 Node* value = jsgraph()->TheHoleConstant();
1104 environment()->Bind(variable, value);
1105 }
1106 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001107 case VariableLocation::CONTEXT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108 if (hole_init) {
1109 Node* value = jsgraph()->TheHoleConstant();
1110 const Operator* op = javascript()->StoreContext(0, variable->index());
1111 NewNode(op, current_context(), value);
1112 }
1113 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001114 case VariableLocation::LOOKUP: {
1115 Node* name = jsgraph()->Constant(variable->name());
1116 // For variables we must not push an initial value (such as 'undefined')
1117 // because we may have a (legal) redeclaration and we must not destroy
1118 // the current value.
1119 Node* value =
1120 hole_init ? jsgraph()->TheHoleConstant()
1121 : jsgraph()->ZeroConstant(); // Indicates no initial value.
1122 Node* attr =
1123 jsgraph()->Constant(variable->DeclarationPropertyAttributes());
1124 const Operator* op =
1125 javascript()->CallRuntime(Runtime::kDeclareLookupSlot);
1126 Node* store = NewNode(op, name, value, attr);
1127 PrepareFrameState(store, decl->proxy()->id());
1128 break;
1129 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 }
1131}
1132
1133
1134void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1135 Variable* variable = decl->proxy()->var();
1136 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 case VariableLocation::GLOBAL:
1138 case VariableLocation::UNALLOCATED: {
1139 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1140 decl->fun(), info()->script(), info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141 // Check for stack-overflow exception.
1142 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143 globals()->push_back(variable->name());
1144 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 break;
1146 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 case VariableLocation::PARAMETER:
1148 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 VisitForValue(decl->fun());
1150 Node* value = environment()->Pop();
1151 environment()->Bind(variable, value);
1152 break;
1153 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 VisitForValue(decl->fun());
1156 Node* value = environment()->Pop();
1157 const Operator* op = javascript()->StoreContext(0, variable->index());
1158 NewNode(op, current_context(), value);
1159 break;
1160 }
Ben Murdochc5610432016-08-08 18:44:38 +01001161 case VariableLocation::LOOKUP: {
1162 VisitForValue(decl->fun());
1163 Node* value = environment()->Pop();
1164 Node* name = jsgraph()->Constant(variable->name());
1165 Node* attr =
1166 jsgraph()->Constant(variable->DeclarationPropertyAttributes());
1167 const Operator* op =
1168 javascript()->CallRuntime(Runtime::kDeclareLookupSlot);
1169 Node* store = NewNode(op, name, value, attr);
1170 PrepareFrameState(store, decl->proxy()->id());
1171 break;
1172 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 }
1174}
1175
1176
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1178 UNREACHABLE();
1179}
1180
1181
1182void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1183 UNREACHABLE();
1184}
1185
1186
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187void AstGraphBuilder::VisitBlock(Block* stmt) {
1188 BlockBuilder block(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001189 ControlScopeForBreakable scope(this, stmt, &block);
1190 if (stmt->labels() != nullptr) block.BeginBlock();
1191 if (stmt->scope() == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 // Visit statements in the same scope, no declarations.
1193 VisitStatements(stmt->statements());
1194 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195 // Visit declarations and statements in a block scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 if (stmt->scope()->NeedsContext()) {
1197 Node* context = BuildLocalBlockContext(stmt->scope());
1198 ContextScope scope(this, stmt->scope(), context);
1199 VisitDeclarations(stmt->scope()->declarations());
1200 VisitStatements(stmt->statements());
1201 } else {
1202 VisitDeclarations(stmt->scope()->declarations());
1203 VisitStatements(stmt->statements());
1204 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 if (stmt->labels() != nullptr) block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207}
1208
1209
1210void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1211 VisitForEffect(stmt->expression());
1212}
1213
1214
1215void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1216 // Do nothing.
1217}
1218
1219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1221 SloppyBlockFunctionStatement* stmt) {
1222 Visit(stmt->statement());
1223}
1224
1225
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1227 IfBuilder compare_if(this);
1228 VisitForTest(stmt->condition());
1229 Node* condition = environment()->Pop();
1230 compare_if.If(condition);
1231 compare_if.Then();
1232 Visit(stmt->then_statement());
1233 compare_if.Else();
1234 Visit(stmt->else_statement());
1235 compare_if.End();
1236}
1237
1238
1239void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 execution_control()->ContinueTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241}
1242
1243
1244void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 execution_control()->BreakTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246}
1247
1248
1249void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1250 VisitForValue(stmt->expression());
1251 Node* result = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 execution_control()->ReturnValue(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253}
1254
1255
1256void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1257 VisitForValue(stmt->expression());
1258 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 Node* object = BuildToObject(value, stmt->ToObjectId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001260 const Operator* op = javascript()->CreateWithContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 Node* context = NewNode(op, object, GetFunctionClosureForContext());
1262 PrepareFrameState(context, stmt->EntryId());
1263 VisitInScope(stmt->statement(), stmt->scope(), context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264}
1265
1266
1267void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1268 ZoneList<CaseClause*>* clauses = stmt->cases();
1269 SwitchBuilder compare_switch(this, clauses->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 ControlScopeForBreakable scope(this, stmt, &compare_switch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 compare_switch.BeginSwitch();
1272 int default_index = -1;
1273
1274 // Keep the switch value on the stack until a case matches.
1275 VisitForValue(stmt->tag());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276
1277 // Iterate over all cases and create nodes for label comparison.
1278 for (int i = 0; i < clauses->length(); i++) {
1279 CaseClause* clause = clauses->at(i);
1280
1281 // The default is not a test, remember index.
1282 if (clause->is_default()) {
1283 default_index = i;
1284 continue;
1285 }
1286
1287 // Create nodes to perform label comparison as if via '==='. The switch
1288 // value is still on the operand stack while the label is evaluated.
1289 VisitForValue(clause->label());
1290 Node* label = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 Node* tag = environment()->Top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 const Operator* op = javascript()->StrictEqual();
1293 Node* condition = NewNode(op, tag, label);
1294 compare_switch.BeginLabel(i, condition);
1295
1296 // Discard the switch value at label match.
1297 environment()->Pop();
1298 compare_switch.EndLabel();
1299 }
1300
1301 // Discard the switch value and mark the default case.
1302 environment()->Pop();
1303 if (default_index >= 0) {
1304 compare_switch.DefaultAt(default_index);
1305 }
1306
1307 // Iterate over all cases and create nodes for case bodies.
1308 for (int i = 0; i < clauses->length(); i++) {
1309 CaseClause* clause = clauses->at(i);
1310 compare_switch.BeginCase(i);
1311 VisitStatements(clause->statements());
1312 compare_switch.EndCase();
1313 }
1314
1315 compare_switch.EndSwitch();
1316}
1317
1318
1319void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1320 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1322 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001323 while_loop.EndBody();
1324 VisitForTest(stmt->cond());
1325 Node* condition = environment()->Pop();
1326 while_loop.BreakUnless(condition);
1327 while_loop.EndLoop();
1328}
1329
1330
1331void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1332 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 VisitForTest(stmt->cond());
1335 Node* condition = environment()->Pop();
1336 while_loop.BreakUnless(condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 while_loop.EndBody();
1339 while_loop.EndLoop();
1340}
1341
1342
1343void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1344 LoopBuilder for_loop(this);
1345 VisitIfNotNull(stmt->init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1347 if (stmt->cond() != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 VisitForTest(stmt->cond());
1349 Node* condition = environment()->Pop();
1350 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001351 } else {
1352 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 for_loop.EndBody();
1356 VisitIfNotNull(stmt->next());
1357 for_loop.EndLoop();
1358}
1359
1360
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1362 VisitForValue(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 Node* object = environment()->Pop();
1364 BlockBuilder for_block(this);
1365 for_block.BeginBlock();
1366 // Check for null or undefined before entering loop.
1367 Node* is_null_cond =
1368 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1369 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1370 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1371 jsgraph()->UndefinedConstant());
1372 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 // Convert object to jsobject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 object = BuildToObject(object, stmt->ToObjectId());
1376 environment()->Push(object);
1377
1378 // Prepare for-in cache.
1379 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001380 PrepareFrameState(prepare, stmt->PrepareId(),
1381 OutputFrameStateCombine::Push(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001382 Node* cache_type = NewNode(common()->Projection(0), prepare);
1383 Node* cache_array = NewNode(common()->Projection(1), prepare);
1384 Node* cache_length = NewNode(common()->Projection(2), prepare);
1385
1386 // Construct the rest of the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 environment()->Push(cache_type);
1388 environment()->Push(cache_array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001389 environment()->Push(cache_length);
1390 environment()->Push(jsgraph()->ZeroConstant());
1391
1392 // Build the actual loop body.
1393 LoopBuilder for_loop(this);
1394 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001395 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 // These stack values are renamed in the case of OSR, so reload them
1397 // from the environment.
1398 Node* index = environment()->Peek(0);
1399 Node* cache_length = environment()->Peek(1);
1400 Node* cache_array = environment()->Peek(2);
1401 Node* cache_type = environment()->Peek(3);
1402 Node* object = environment()->Peek(4);
1403
1404 // Check loop termination condition.
1405 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1406 for_loop.BreakWhen(exit_cond);
1407
1408 // Compute the next enumerated value.
1409 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1410 cache_type, index);
1411 PrepareFrameState(value, stmt->FilterId(),
1412 OutputFrameStateCombine::Push());
1413 IfBuilder test_value(this);
1414 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1415 jsgraph()->UndefinedConstant());
1416 test_value.If(test_value_cond, BranchHint::kFalse);
1417 test_value.Then();
1418 test_value.Else();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001419 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420 // Bind value and do loop body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001421 VectorSlotPair feedback =
1422 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1423 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1424 stmt->AssignmentId());
1425 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001427 test_value.End();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001428 for_loop.EndBody();
1429
1430 // Increment counter and continue.
Ben Murdochc5610432016-08-08 18:44:38 +01001431 index = environment()->Peek(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001432 index = NewNode(javascript()->ForInStep(), index);
1433 environment()->Poke(0, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 for_loop.EndLoop();
1436 environment()->Drop(5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001437 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 for_block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439}
1440
1441
1442void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 LoopBuilder for_loop(this);
1444 VisitForEffect(stmt->assign_iterator());
1445 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1446 VisitForEffect(stmt->next_result());
1447 VisitForTest(stmt->result_done());
1448 Node* condition = environment()->Pop();
1449 for_loop.BreakWhen(condition);
1450 VisitForEffect(stmt->assign_each());
1451 VisitIterationBody(stmt, &for_loop);
1452 for_loop.EndBody();
1453 for_loop.EndLoop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001454}
1455
1456
1457void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 TryCatchBuilder try_control(this);
1459
1460 // Evaluate the try-block inside a control scope. This simulates a handler
1461 // that is intercepting 'throw' control commands.
1462 try_control.BeginTry();
1463 {
1464 ControlScopeForCatch scope(this, &try_control);
1465 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1466 environment()->Push(current_context());
1467 Visit(stmt->try_block());
1468 environment()->Pop();
1469 }
1470 try_control.EndTry();
1471
Ben Murdochda12d292016-06-02 14:46:10 +01001472 // If requested, clear message object as we enter the catch block.
1473 if (stmt->clear_pending_message()) {
1474 Node* the_hole = jsgraph()->TheHoleConstant();
1475 NewNode(javascript()->StoreMessage(), the_hole);
1476 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477
1478 // Create a catch scope that binds the exception.
1479 Node* exception = try_control.GetExceptionNode();
1480 Handle<String> name = stmt->variable()->name();
1481 const Operator* op = javascript()->CreateCatchContext(name);
1482 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1483
1484 // Evaluate the catch-block.
1485 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1486 try_control.EndCatch();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487}
1488
1489
1490void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001491 TryFinallyBuilder try_control(this);
1492
1493 // We keep a record of all paths that enter the finally-block to be able to
1494 // dispatch to the correct continuation point after the statements in the
1495 // finally-block have been evaluated.
1496 //
1497 // The try-finally construct can enter the finally-block in three ways:
1498 // 1. By exiting the try-block normally, falling through at the end.
1499 // 2. By exiting the try-block with a function-local control flow transfer
1500 // (i.e. through break/continue/return statements).
1501 // 3. By exiting the try-block with a thrown exception.
1502 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1503 ControlScope::DeferredCommands* commands =
1504 new (local_zone()) ControlScope::DeferredCommands(this);
1505
1506 // Evaluate the try-block inside a control scope. This simulates a handler
1507 // that is intercepting all control commands.
1508 try_control.BeginTry();
1509 {
1510 ControlScopeForFinally scope(this, commands, &try_control);
1511 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1512 environment()->Push(current_context());
1513 Visit(stmt->try_block());
1514 environment()->Pop();
1515 }
1516 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518 // The result value semantics depend on how the block was entered:
1519 // - ReturnStatement: It represents the return value being returned.
1520 // - ThrowStatement: It represents the exception being thrown.
1521 // - BreakStatement/ContinueStatement: Filled with the hole.
1522 // - Falling through into finally-block: Filled with the hole.
1523 Node* result = try_control.GetResultValueNode();
1524 Node* token = try_control.GetDispatchTokenNode();
1525
1526 // The result value, dispatch token and message is expected on the operand
1527 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1528 Node* message = NewNode(javascript()->LoadMessage());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001529 environment()->Push(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 environment()->Push(result);
1531 environment()->Push(message);
1532
1533 // Clear message object as we enter the finally block.
1534 Node* the_hole = jsgraph()->TheHoleConstant();
1535 NewNode(javascript()->StoreMessage(), the_hole);
1536
1537 // Evaluate the finally-block.
1538 Visit(stmt->finally_block());
1539 try_control.EndFinally();
1540
1541 // The result value, dispatch token and message is restored from the operand
1542 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1543 message = environment()->Pop();
1544 result = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001545 token = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 NewNode(javascript()->StoreMessage(), message);
1547
1548 // Dynamic dispatch after the finally-block.
1549 commands->ApplyDeferredCommands(token, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550}
1551
1552
1553void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001554 Node* node =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001555 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 PrepareFrameState(node, stmt->DebugBreakId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001557 environment()->MarkAllLocalsLive();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001558}
1559
1560
1561void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001562 // Find or build a shared function info.
1563 Handle<SharedFunctionInfo> shared_info =
1564 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1565 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001566
1567 // Create node to instantiate a new closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568 PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1569 const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1570 Node* value = NewNode(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 ast_context()->ProduceValue(value);
1572}
1573
1574
1575void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 // Visit declarations and class literal in a block scope.
1577 if (expr->scope()->ContextLocalCount() > 0) {
1578 Node* context = BuildLocalBlockContext(expr->scope());
1579 ContextScope scope(this, expr->scope(), context);
1580 VisitDeclarations(expr->scope()->declarations());
1581 VisitClassLiteralContents(expr);
1582 } else {
1583 VisitDeclarations(expr->scope()->declarations());
1584 VisitClassLiteralContents(expr);
1585 }
1586}
1587
1588
1589void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590 VisitForValueOrTheHole(expr->extends());
1591 VisitForValue(expr->constructor());
1592
1593 // Create node to instantiate a new class.
1594 Node* constructor = environment()->Pop();
1595 Node* extends = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001596 Node* start = jsgraph()->Constant(expr->start_position());
1597 Node* end = jsgraph()->Constant(expr->end_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001598 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
1599 Node* literal = NewNode(opc, extends, constructor, start, end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001600 PrepareFrameState(literal, expr->CreateLiteralId(),
1601 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001602 environment()->Push(literal);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001603
1604 // Load the "prototype" from the constructor.
1605 FrameStateBeforeAndAfter states(this, expr->CreateLiteralId());
1606 Handle<Name> name = isolate()->factory()->prototype_string();
1607 VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
1608 Node* prototype = BuildNamedLoad(literal, name, pair);
1609 states.AddToNode(prototype, expr->PrototypeId(),
1610 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 environment()->Push(prototype);
1612
1613 // Create nodes to store method values into the literal.
1614 for (int i = 0; i < expr->properties()->length(); i++) {
1615 ObjectLiteral::Property* property = expr->properties()->at(i);
1616 environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1617
1618 VisitForValue(property->key());
1619 Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1620 environment()->Push(name);
1621
1622 // The static prototype property is read only. We handle the non computed
1623 // property name case in the parser. Since this is the only case where we
1624 // need to check for an own read only property we special case this so we do
1625 // not need to do this for every property.
1626 if (property->is_static() && property->is_computed_name()) {
1627 Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1628 expr->GetIdForProperty(i));
1629 environment()->Push(check);
1630 }
1631
1632 VisitForValue(property->value());
1633 Node* value = environment()->Pop();
1634 Node* key = environment()->Pop();
1635 Node* receiver = environment()->Pop();
1636
1637 BuildSetHomeObject(value, receiver, property);
1638
1639 switch (property->kind()) {
1640 case ObjectLiteral::Property::CONSTANT:
1641 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1642 case ObjectLiteral::Property::PROTOTYPE:
1643 UNREACHABLE();
1644 case ObjectLiteral::Property::COMPUTED: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001645 Node* attr = jsgraph()->Constant(DONT_ENUM);
1646 Node* set_function_name =
1647 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001649 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1650 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 break;
1652 }
1653 case ObjectLiteral::Property::GETTER: {
1654 Node* attr = jsgraph()->Constant(DONT_ENUM);
1655 const Operator* op = javascript()->CallRuntime(
1656 Runtime::kDefineGetterPropertyUnchecked, 4);
1657 NewNode(op, receiver, key, value, attr);
1658 break;
1659 }
1660 case ObjectLiteral::Property::SETTER: {
1661 Node* attr = jsgraph()->Constant(DONT_ENUM);
1662 const Operator* op = javascript()->CallRuntime(
1663 Runtime::kDefineSetterPropertyUnchecked, 4);
1664 NewNode(op, receiver, key, value, attr);
1665 break;
1666 }
1667 }
1668 }
1669
Ben Murdochc5610432016-08-08 18:44:38 +01001670 // Set the constructor to have fast properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671 prototype = environment()->Pop();
1672 literal = environment()->Pop();
Ben Murdochc5610432016-08-08 18:44:38 +01001673 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
1674 literal = NewNode(op, literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675
1676 // Assign to class variable.
1677 if (expr->class_variable_proxy() != nullptr) {
1678 Variable* var = expr->class_variable_proxy()->var();
1679 FrameStateBeforeAndAfter states(this, BailoutId::None());
1680 VectorSlotPair feedback = CreateVectorSlotPair(
1681 expr->NeedsProxySlot() ? expr->ProxySlot()
1682 : FeedbackVectorSlot::Invalid());
1683 BuildVariableAssignment(var, literal, Token::INIT, feedback,
1684 BailoutId::None(), states);
1685 }
1686 ast_context()->ProduceValue(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001687}
1688
1689
1690void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1691 UNREACHABLE();
1692}
1693
1694
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001695void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1696 VisitBlock(expr->block());
1697 VisitVariableProxy(expr->result());
1698 ast_context()->ReplaceValue();
1699}
1700
1701
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001702void AstGraphBuilder::VisitConditional(Conditional* expr) {
1703 IfBuilder compare_if(this);
1704 VisitForTest(expr->condition());
1705 Node* condition = environment()->Pop();
1706 compare_if.If(condition);
1707 compare_if.Then();
1708 Visit(expr->then_expression());
1709 compare_if.Else();
1710 Visit(expr->else_expression());
1711 compare_if.End();
1712 ast_context()->ReplaceValue();
1713}
1714
1715
1716void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001717 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718 FrameStateBeforeAndAfter states(this, BeforeId(expr));
1719 Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
1720 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001721 ast_context()->ProduceValue(value);
1722}
1723
1724
1725void AstGraphBuilder::VisitLiteral(Literal* expr) {
1726 Node* value = jsgraph()->Constant(expr->value());
1727 ast_context()->ProduceValue(value);
1728}
1729
1730
1731void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1732 Node* closure = GetFunctionClosure();
1733
1734 // Create node to materialize a regular expression literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 const Operator* op = javascript()->CreateLiteralRegExp(
1736 expr->pattern(), expr->flags(), expr->literal_index());
1737 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001738 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001739 ast_context()->ProduceValue(literal);
1740}
1741
1742
1743void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1744 Node* closure = GetFunctionClosure();
1745
1746 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 const Operator* op = javascript()->CreateLiteralObject(
1748 expr->constant_properties(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001749 expr->literal_index(), expr->properties_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001750 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001751 PrepareFrameState(literal, expr->CreateLiteralId(),
1752 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753
1754 // The object is expected on the operand stack during computation of the
1755 // property values and is the value of the entire expression.
1756 environment()->Push(literal);
1757
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 // Create nodes to store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001759 int property_index = 0;
1760 AccessorTable accessor_table(local_zone());
1761 for (; property_index < expr->properties()->length(); property_index++) {
1762 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1763 if (property->is_computed_name()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001764 if (property->IsCompileTimeValue()) continue;
1765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001766 Literal* key = property->key()->AsLiteral();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001767 switch (property->kind()) {
1768 case ObjectLiteral::Property::CONSTANT:
1769 UNREACHABLE();
1770 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1771 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1772 // Fall through.
1773 case ObjectLiteral::Property::COMPUTED: {
1774 // It is safe to use [[Put]] here because the boilerplate already
1775 // contains computed properties with an uninitialized value.
1776 if (key->value()->IsInternalizedString()) {
1777 if (property->emit_store()) {
1778 VisitForValue(property->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 FrameStateBeforeAndAfter states(this, property->value()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001780 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001781 Node* literal = environment()->Top();
1782 Handle<Name> name = key->AsPropertyName();
1783 VectorSlotPair feedback =
1784 CreateVectorSlotPair(property->GetSlot(0));
1785 Node* store = BuildNamedStore(literal, name, value, feedback);
1786 states.AddToNode(store, key->id(),
1787 OutputFrameStateCombine::Ignore());
1788 BuildSetHomeObject(value, literal, property, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001789 } else {
1790 VisitForEffect(property->value());
1791 }
1792 break;
1793 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001794 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 VisitForValue(property->key());
1796 VisitForValue(property->value());
1797 Node* value = environment()->Pop();
1798 Node* key = environment()->Pop();
1799 Node* receiver = environment()->Pop();
1800 if (property->emit_store()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001801 Node* language = jsgraph()->Constant(SLOPPY);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001802 const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001803 Node* set_property = NewNode(op, receiver, key, value, language);
1804 // SetProperty should not lazy deopt on an object literal.
1805 PrepareFrameState(set_property, BailoutId::None());
1806 BuildSetHomeObject(value, receiver, property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807 }
1808 break;
1809 }
1810 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001811 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812 VisitForValue(property->value());
1813 Node* value = environment()->Pop();
1814 Node* receiver = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 DCHECK(property->emit_store());
1816 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001817 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 Node* set_prototype = NewNode(op, receiver, value);
1819 // SetPrototype should not lazy deopt on an object literal.
1820 PrepareFrameState(set_prototype,
1821 expr->GetIdForPropertySet(property_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001822 break;
1823 }
1824 case ObjectLiteral::Property::GETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825 if (property->emit_store()) {
1826 accessor_table.lookup(key)->second->getter = property;
1827 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 break;
1829 case ObjectLiteral::Property::SETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 if (property->emit_store()) {
1831 accessor_table.lookup(key)->second->setter = property;
1832 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 break;
1834 }
1835 }
1836
1837 // Create nodes to define accessors, using only a single call to the runtime
1838 // for each pair of corresponding getters and setters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 for (AccessorTable::Iterator it = accessor_table.begin();
1841 it != accessor_table.end(); ++it) {
1842 VisitForValue(it->first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001843 VisitObjectLiteralAccessor(literal, it->second->getter);
1844 VisitObjectLiteralAccessor(literal, it->second->setter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 Node* setter = environment()->Pop();
1846 Node* getter = environment()->Pop();
1847 Node* name = environment()->Pop();
1848 Node* attr = jsgraph()->Constant(NONE);
1849 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001850 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001851 Node* call = NewNode(op, literal, name, getter, setter, attr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001852 // This should not lazy deopt on a new literal.
1853 PrepareFrameState(call, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001854 }
1855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001856 // Object literals have two parts. The "static" part on the left contains no
1857 // computed property names, and so we can compute its map ahead of time; see
1858 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1859 // with the first computed property name and continues with all properties to
1860 // its right. All the code from above initializes the static component of the
1861 // object literal, and arranges for the map of the result to reflect the
1862 // static order in which the keys appear. For the dynamic properties, we
1863 // compile them into a series of "SetOwnProperty" runtime calls. This will
1864 // preserve insertion order.
1865 for (; property_index < expr->properties()->length(); property_index++) {
1866 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1867
1868 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1869 environment()->Push(environment()->Top()); // Duplicate receiver.
1870 VisitForValue(property->value());
1871 Node* value = environment()->Pop();
1872 Node* receiver = environment()->Pop();
1873 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001874 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001875 Node* call = NewNode(op, receiver, value);
1876 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1877 continue;
1878 }
1879
1880 environment()->Push(environment()->Top()); // Duplicate receiver.
1881 VisitForValue(property->key());
1882 Node* name = BuildToName(environment()->Pop(),
1883 expr->GetIdForPropertyName(property_index));
1884 environment()->Push(name);
1885 VisitForValue(property->value());
1886 Node* value = environment()->Pop();
1887 Node* key = environment()->Pop();
1888 Node* receiver = environment()->Pop();
1889 BuildSetHomeObject(value, receiver, property);
1890 switch (property->kind()) {
1891 case ObjectLiteral::Property::CONSTANT:
1892 case ObjectLiteral::Property::COMPUTED:
1893 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1894 Node* attr = jsgraph()->Constant(NONE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001895 Node* set_function_name =
1896 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001897 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001898 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1899 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001900 break;
1901 }
1902 case ObjectLiteral::Property::PROTOTYPE:
1903 UNREACHABLE(); // Handled specially above.
1904 break;
1905 case ObjectLiteral::Property::GETTER: {
1906 Node* attr = jsgraph()->Constant(NONE);
1907 const Operator* op = javascript()->CallRuntime(
1908 Runtime::kDefineGetterPropertyUnchecked, 4);
1909 Node* call = NewNode(op, receiver, key, value, attr);
1910 PrepareFrameState(call, BailoutId::None());
1911 break;
1912 }
1913 case ObjectLiteral::Property::SETTER: {
1914 Node* attr = jsgraph()->Constant(NONE);
1915 const Operator* op = javascript()->CallRuntime(
1916 Runtime::kDefineSetterPropertyUnchecked, 4);
1917 Node* call = NewNode(op, receiver, key, value, attr);
1918 PrepareFrameState(call, BailoutId::None());
1919 break;
1920 }
1921 }
1922 }
1923
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001924 ast_context()->ProduceValue(environment()->Pop());
1925}
1926
1927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001928void AstGraphBuilder::VisitObjectLiteralAccessor(
1929 Node* home_object, ObjectLiteralProperty* property) {
1930 if (property == nullptr) {
1931 VisitForValueOrNull(nullptr);
1932 } else {
1933 VisitForValue(property->value());
1934 BuildSetHomeObject(environment()->Top(), home_object, property);
1935 }
1936}
1937
1938
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1940 Node* closure = GetFunctionClosure();
1941
1942 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001943 const Operator* op = javascript()->CreateLiteralArray(
1944 expr->constant_elements(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001945 expr->literal_index(), expr->values()->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001946 Node* literal = NewNode(op, closure);
1947 PrepareFrameState(literal, expr->CreateLiteralId(),
1948 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001949
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001950 // The array is expected on the operand stack during computation of the
1951 // element values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001952 environment()->Push(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953
1954 // Create nodes to evaluate all the non-constant subexpressions and to store
1955 // them into the newly cloned array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001956 int array_index = 0;
1957 for (; array_index < expr->values()->length(); array_index++) {
1958 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001959 DCHECK(!subexpr->IsSpread());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001960 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1961
1962 VisitForValue(subexpr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001963 {
1964 FrameStateBeforeAndAfter states(this, subexpr->id());
1965 VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1966 Node* value = environment()->Pop();
1967 Node* index = jsgraph()->Constant(array_index);
1968 Node* literal = environment()->Top();
1969 Node* store = BuildKeyedStore(literal, index, value, pair);
1970 states.AddToNode(store, expr->GetIdForElement(array_index),
1971 OutputFrameStateCombine::Ignore());
1972 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001973 }
1974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001975 // In case the array literal contains spread expressions it has two parts. The
1976 // first part is the "static" array which has a literal index is handled
1977 // above. The second part is the part after the first spread expression
1978 // (inclusive) and these elements gets appended to the array. Note that the
1979 // number elements an iterable produces is unknown ahead of time.
1980 for (; array_index < expr->values()->length(); array_index++) {
1981 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001982 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001983
Ben Murdoch097c5b22016-05-18 11:27:45 +01001984 VisitForValue(subexpr);
1985 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001986 Node* value = environment()->Pop();
1987 Node* array = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001988 const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
1989 Node* result = NewNode(op, array, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001990 PrepareFrameState(result, expr->GetIdForElement(array_index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001991 environment()->Push(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001992 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001993 }
1994
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001995 ast_context()->ProduceValue(environment()->Pop());
1996}
1997
1998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001999void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
2000 const VectorSlotPair& feedback,
2001 BailoutId bailout_id_before,
2002 BailoutId bailout_id_after) {
2003 DCHECK(expr->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004
2005 // Left-hand side can only be a property, a global or a variable slot.
2006 Property* property = expr->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002007 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002008
2009 // Evaluate LHS expression and store the value.
2010 switch (assign_type) {
2011 case VARIABLE: {
2012 Variable* var = expr->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002013 environment()->Push(value);
2014 FrameStateBeforeAndAfter states(this, bailout_id_before);
2015 value = environment()->Pop();
2016 BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
2017 bailout_id_after, states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002018 break;
2019 }
2020 case NAMED_PROPERTY: {
2021 environment()->Push(value);
2022 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002023 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002024 Node* object = environment()->Pop();
2025 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002026 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2027 Node* store = BuildNamedStore(object, name, value, feedback);
2028 states.AddToNode(store, bailout_id_after,
2029 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002030 break;
2031 }
2032 case KEYED_PROPERTY: {
2033 environment()->Push(value);
2034 VisitForValue(property->obj());
2035 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002036 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002037 Node* key = environment()->Pop();
2038 Node* object = environment()->Pop();
2039 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002040 Node* store = BuildKeyedStore(object, key, value, feedback);
2041 states.AddToNode(store, bailout_id_after,
2042 OutputFrameStateCombine::Ignore());
2043 break;
2044 }
2045 case NAMED_SUPER_PROPERTY: {
2046 environment()->Push(value);
2047 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2048 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2049 FrameStateBeforeAndAfter states(this, property->obj()->id());
2050 Node* home_object = environment()->Pop();
2051 Node* receiver = environment()->Pop();
2052 value = environment()->Pop();
2053 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2054 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2055 states.AddToNode(store, bailout_id_after,
2056 OutputFrameStateCombine::Ignore());
2057 break;
2058 }
2059 case KEYED_SUPER_PROPERTY: {
2060 environment()->Push(value);
2061 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2062 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2063 VisitForValue(property->key());
2064 FrameStateBeforeAndAfter states(this, property->key()->id());
2065 Node* key = environment()->Pop();
2066 Node* home_object = environment()->Pop();
2067 Node* receiver = environment()->Pop();
2068 value = environment()->Pop();
2069 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2070 states.AddToNode(store, bailout_id_after,
2071 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002072 break;
2073 }
2074 }
2075}
2076
2077
2078void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002079 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002080
2081 // Left-hand side can only be a property, a global or a variable slot.
2082 Property* property = expr->target()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002083 LhsKind assign_type = Property::GetAssignType(property);
2084 bool needs_frame_state_before = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002085
2086 // Evaluate LHS expression.
2087 switch (assign_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002088 case VARIABLE: {
2089 Variable* variable = expr->target()->AsVariableProxy()->var();
2090 if (variable->location() == VariableLocation::PARAMETER ||
2091 variable->location() == VariableLocation::LOCAL ||
2092 variable->location() == VariableLocation::CONTEXT) {
2093 needs_frame_state_before = false;
2094 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002095 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002096 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002097 case NAMED_PROPERTY:
2098 VisitForValue(property->obj());
2099 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002100 case KEYED_PROPERTY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002101 VisitForValue(property->obj());
2102 VisitForValue(property->key());
2103 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002104 case NAMED_SUPER_PROPERTY:
2105 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2106 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2107 break;
2108 case KEYED_SUPER_PROPERTY:
2109 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2110 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2111 VisitForValue(property->key());
2112 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002113 }
2114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002115 BailoutId before_store_id = BailoutId::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002116 // Evaluate the value and potentially handle compound assignments by loading
2117 // the left-hand side value and performing a binary operation.
2118 if (expr->is_compound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002119 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002120 switch (assign_type) {
2121 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002122 VariableProxy* proxy = expr->target()->AsVariableProxy();
2123 VectorSlotPair pair =
2124 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002125 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2126 old_value =
2127 BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
2128 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002129 break;
2130 }
2131 case NAMED_PROPERTY: {
2132 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002133 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002134 VectorSlotPair pair =
2135 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002136 FrameStateBeforeAndAfter states(this, property->obj()->id());
2137 old_value = BuildNamedLoad(object, name, pair);
2138 states.AddToNode(old_value, property->LoadId(),
2139 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002140 break;
2141 }
2142 case KEYED_PROPERTY: {
2143 Node* key = environment()->Top();
2144 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002145 VectorSlotPair pair =
2146 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002147 FrameStateBeforeAndAfter states(this, property->key()->id());
2148 old_value = BuildKeyedLoad(object, key, pair);
2149 states.AddToNode(old_value, property->LoadId(),
2150 OutputFrameStateCombine::Push());
2151 break;
2152 }
2153 case NAMED_SUPER_PROPERTY: {
2154 Node* home_object = environment()->Top();
2155 Node* receiver = environment()->Peek(1);
2156 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2157 VectorSlotPair pair =
2158 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2159 FrameStateBeforeAndAfter states(this, property->obj()->id());
2160 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2161 states.AddToNode(old_value, property->LoadId(),
2162 OutputFrameStateCombine::Push());
2163 break;
2164 }
2165 case KEYED_SUPER_PROPERTY: {
2166 Node* key = environment()->Top();
2167 Node* home_object = environment()->Peek(1);
2168 Node* receiver = environment()->Peek(2);
2169 VectorSlotPair pair =
2170 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2171 FrameStateBeforeAndAfter states(this, property->key()->id());
2172 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2173 states.AddToNode(old_value, property->LoadId(),
2174 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 break;
2176 }
2177 }
2178 environment()->Push(old_value);
2179 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002180 Node* value;
2181 {
2182 FrameStateBeforeAndAfter states(this, expr->value()->id());
2183 Node* right = environment()->Pop();
2184 Node* left = environment()->Pop();
2185 value =
2186 BuildBinaryOp(left, right, expr->binary_op(),
2187 expr->binary_operation()->BinaryOperationFeedbackId());
2188 states.AddToNode(value, expr->binary_operation()->id(),
2189 OutputFrameStateCombine::Push());
2190 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002191 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002192 if (needs_frame_state_before) {
2193 before_store_id = expr->binary_operation()->id();
2194 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002195 } else {
2196 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002197 if (needs_frame_state_before) {
2198 before_store_id = expr->value()->id();
2199 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002200 }
2201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002202 FrameStateBeforeAndAfter store_states(this, before_store_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002203 // Store the value.
2204 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002205 VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002206 switch (assign_type) {
2207 case VARIABLE: {
2208 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002209 BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2210 store_states, ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002211 break;
2212 }
2213 case NAMED_PROPERTY: {
2214 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002215 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2216 Node* store = BuildNamedStore(object, name, value, feedback);
2217 store_states.AddToNode(store, expr->id(),
2218 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 break;
2220 }
2221 case KEYED_PROPERTY: {
2222 Node* key = environment()->Pop();
2223 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002224 Node* store = BuildKeyedStore(object, key, value, feedback);
2225 store_states.AddToNode(store, expr->id(),
2226 ast_context()->GetStateCombine());
2227 break;
2228 }
2229 case NAMED_SUPER_PROPERTY: {
2230 Node* home_object = environment()->Pop();
2231 Node* receiver = environment()->Pop();
2232 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2233 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2234 store_states.AddToNode(store, expr->id(),
2235 ast_context()->GetStateCombine());
2236 break;
2237 }
2238 case KEYED_SUPER_PROPERTY: {
2239 Node* key = environment()->Pop();
2240 Node* home_object = environment()->Pop();
2241 Node* receiver = environment()->Pop();
2242 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2243 store_states.AddToNode(store, expr->id(),
2244 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002245 break;
2246 }
2247 }
2248
2249 ast_context()->ProduceValue(value);
2250}
2251
2252
2253void AstGraphBuilder::VisitYield(Yield* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01002254 // Generator functions are supported only by going through Ignition first.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002255 SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002256 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2257}
2258
2259
2260void AstGraphBuilder::VisitThrow(Throw* expr) {
2261 VisitForValue(expr->exception());
2262 Node* exception = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002263 Node* value = BuildThrowError(exception, expr->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002264 ast_context()->ProduceValue(value);
2265}
2266
2267
2268void AstGraphBuilder::VisitProperty(Property* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002269 Node* value = nullptr;
2270 LhsKind property_kind = Property::GetAssignType(expr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002271 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002272 switch (property_kind) {
2273 case VARIABLE:
2274 UNREACHABLE();
2275 break;
2276 case NAMED_PROPERTY: {
2277 VisitForValue(expr->obj());
2278 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2279 Node* object = environment()->Pop();
2280 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2281 value = BuildNamedLoad(object, name, pair);
2282 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2283 break;
2284 }
2285 case KEYED_PROPERTY: {
2286 VisitForValue(expr->obj());
2287 VisitForValue(expr->key());
2288 FrameStateBeforeAndAfter states(this, expr->key()->id());
2289 Node* key = environment()->Pop();
2290 Node* object = environment()->Pop();
2291 value = BuildKeyedLoad(object, key, pair);
2292 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2293 break;
2294 }
2295 case NAMED_SUPER_PROPERTY: {
2296 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2297 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2298 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2299 Node* home_object = environment()->Pop();
2300 Node* receiver = environment()->Pop();
2301 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2302 value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2303 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2304 break;
2305 }
2306 case KEYED_SUPER_PROPERTY: {
2307 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2308 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2309 VisitForValue(expr->key());
2310 FrameStateBeforeAndAfter states(this, expr->key()->id());
2311 Node* key = environment()->Pop();
2312 Node* home_object = environment()->Pop();
2313 Node* receiver = environment()->Pop();
2314 value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2315 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2316 break;
2317 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002318 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002319 ast_context()->ProduceValue(value);
2320}
2321
2322
2323void AstGraphBuilder::VisitCall(Call* expr) {
2324 Expression* callee = expr->expression();
2325 Call::CallType call_type = expr->GetCallType(isolate());
2326
2327 // Prepare the callee and the receiver to the function call. This depends on
2328 // the semantics of the underlying call type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002329 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2330 Node* receiver_value = nullptr;
2331 Node* callee_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002332 bool possibly_eval = false;
2333 switch (call_type) {
2334 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002335 VariableProxy* proxy = callee->AsVariableProxy();
2336 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002337 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002338 callee_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002339 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2340 pair, OutputFrameStateCombine::Push());
2341 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002342 receiver_value = jsgraph()->UndefinedConstant();
2343 break;
2344 }
2345 case Call::LOOKUP_SLOT_CALL: {
2346 Variable* variable = callee->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002347 DCHECK(variable->location() == VariableLocation::LOOKUP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002348 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002349 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002350 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2351 Node* pair = NewNode(op, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352 callee_value = NewNode(common()->Projection(0), pair);
2353 receiver_value = NewNode(common()->Projection(1), pair);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002354 PrepareFrameState(pair, expr->LookupId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002355 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002356 break;
2357 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002358 case Call::NAMED_PROPERTY_CALL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002359 Property* property = callee->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002360 VectorSlotPair feedback =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002361 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002362 VisitForValue(property->obj());
2363 FrameStateBeforeAndAfter states(this, property->obj()->id());
2364 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2365 Node* object = environment()->Top();
2366 callee_value = BuildNamedLoad(object, name, feedback);
2367 states.AddToNode(callee_value, property->LoadId(),
2368 OutputFrameStateCombine::Push());
2369 // Note that a property call requires the receiver to be wrapped into
2370 // an object for sloppy callees. However the receiver is guaranteed
2371 // not to be null or undefined at this point.
2372 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002373 receiver_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002374 break;
2375 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002376 case Call::KEYED_PROPERTY_CALL: {
2377 Property* property = callee->AsProperty();
2378 VectorSlotPair feedback =
2379 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2380 VisitForValue(property->obj());
2381 VisitForValue(property->key());
2382 FrameStateBeforeAndAfter states(this, property->key()->id());
2383 Node* key = environment()->Pop();
2384 Node* object = environment()->Top();
2385 callee_value = BuildKeyedLoad(object, key, feedback);
2386 states.AddToNode(callee_value, property->LoadId(),
2387 OutputFrameStateCombine::Push());
2388 // Note that a property call requires the receiver to be wrapped into
2389 // an object for sloppy callees. However the receiver is guaranteed
2390 // not to be null or undefined at this point.
2391 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2392 receiver_value = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002393 break;
2394 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002395 case Call::NAMED_SUPER_PROPERTY_CALL: {
2396 Property* property = callee->AsProperty();
2397 SuperPropertyReference* super_ref =
2398 property->obj()->AsSuperPropertyReference();
2399 VisitForValue(super_ref->home_object());
2400 VisitForValue(super_ref->this_var());
2401 Node* home = environment()->Peek(1);
2402 Node* object = environment()->Top();
2403 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2404 FrameStateBeforeAndAfter states(this, property->obj()->id());
2405 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
2406 states.AddToNode(callee_value, property->LoadId(),
2407 OutputFrameStateCombine::Push());
2408 // Note that a property call requires the receiver to be wrapped into
2409 // an object for sloppy callees. Since the receiver is not the target of
2410 // the load, it could very well be null or undefined at this point.
2411 receiver_value = environment()->Pop();
2412 environment()->Drop(1);
2413 break;
2414 }
2415 case Call::KEYED_SUPER_PROPERTY_CALL: {
2416 Property* property = callee->AsProperty();
2417 SuperPropertyReference* super_ref =
2418 property->obj()->AsSuperPropertyReference();
2419 VisitForValue(super_ref->home_object());
2420 VisitForValue(super_ref->this_var());
2421 environment()->Push(environment()->Top()); // Duplicate this_var.
2422 environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
2423 VisitForValue(property->key());
2424 Node* key = environment()->Pop();
2425 Node* home = environment()->Pop();
2426 Node* object = environment()->Pop();
2427 FrameStateBeforeAndAfter states(this, property->key()->id());
2428 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
2429 states.AddToNode(callee_value, property->LoadId(),
2430 OutputFrameStateCombine::Push());
2431 // Note that a property call requires the receiver to be wrapped into
2432 // an object for sloppy callees. Since the receiver is not the target of
2433 // the load, it could very well be null or undefined at this point.
2434 receiver_value = environment()->Pop();
2435 environment()->Drop(1);
2436 break;
2437 }
2438 case Call::SUPER_CALL:
2439 return VisitCallSuper(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440 case Call::POSSIBLY_EVAL_CALL:
2441 possibly_eval = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002442 if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2443 Variable* variable = callee->AsVariableProxy()->var();
2444 Node* name = jsgraph()->Constant(variable->name());
2445 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002446 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2447 Node* pair = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002448 callee_value = NewNode(common()->Projection(0), pair);
2449 receiver_value = NewNode(common()->Projection(1), pair);
2450 PrepareFrameState(pair, expr->LookupId(),
2451 OutputFrameStateCombine::Push(2));
2452 break;
2453 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002454 // Fall through.
2455 case Call::OTHER_CALL:
2456 VisitForValue(callee);
2457 callee_value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002458 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002459 receiver_value = jsgraph()->UndefinedConstant();
2460 break;
2461 }
2462
2463 // The callee and the receiver both have to be pushed onto the operand stack
2464 // before arguments are being evaluated.
2465 environment()->Push(callee_value);
2466 environment()->Push(receiver_value);
2467
2468 // Evaluate all arguments to the function call,
2469 ZoneList<Expression*>* args = expr->arguments();
2470 VisitForValues(args);
2471
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002472 // Resolve callee for a potential direct eval call. This block will mutate the
2473 // callee value pushed onto the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474 if (possibly_eval && args->length() > 0) {
2475 int arg_count = args->length();
2476
2477 // Extract callee and source string from the environment.
2478 Node* callee = environment()->Peek(arg_count + 1);
2479 Node* source = environment()->Peek(arg_count - 1);
2480
2481 // Create node to ask for help resolving potential eval call. This will
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002482 // provide a fully resolved callee to patch into the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002483 Node* function = GetFunctionClosure();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 Node* language = jsgraph()->Constant(language_mode());
Ben Murdochc5610432016-08-08 18:44:38 +01002485 Node* eval_scope_position =
2486 jsgraph()->Constant(current_scope()->start_position());
2487 Node* eval_position = jsgraph()->Constant(expr->position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002489 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Ben Murdochc5610432016-08-08 18:44:38 +01002490 Node* new_callee = NewNode(op, callee, source, function, language,
2491 eval_scope_position, eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002492 PrepareFrameState(new_callee, expr->EvalId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002493 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002495 // Patch callee on the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002496 environment()->Poke(arg_count + 1, new_callee);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497 }
2498
2499 // Create node to perform the function call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002500 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2501 const Operator* call = javascript()->CallFunction(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002502 args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002503 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002504 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002505 environment()->Push(value->InputAt(0)); // The callee passed to the call.
2506 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2507 environment()->Drop(1);
2508 ast_context()->ProduceValue(value);
2509}
2510
2511
2512void AstGraphBuilder::VisitCallSuper(Call* expr) {
2513 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2514 DCHECK_NOT_NULL(super);
2515
2516 // Prepare the callee to the super call.
2517 VisitForValue(super->this_function_var());
2518 Node* this_function = environment()->Pop();
2519 const Operator* op =
2520 javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2521 Node* super_function = NewNode(op, this_function);
2522 environment()->Push(super_function);
2523
2524 // Evaluate all arguments to the super call.
2525 ZoneList<Expression*>* args = expr->arguments();
2526 VisitForValues(args);
2527
2528 // The new target is loaded from the {new.target} variable.
2529 VisitForValue(super->new_target_var());
2530
2531 // Create node to perform the super call.
2532 const Operator* call =
2533 javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
2534 FrameStateBeforeAndAfter states(this, super->new_target_var()->id());
2535 Node* value = ProcessArguments(call, args->length() + 2);
2536 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002537 ast_context()->ProduceValue(value);
2538}
2539
2540
2541void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2542 VisitForValue(expr->expression());
2543
2544 // Evaluate all arguments to the construct call.
2545 ZoneList<Expression*>* args = expr->arguments();
2546 VisitForValues(args);
2547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002548 // The baseline compiler doesn't push the new.target, so we need to record
2549 // the frame state before the push.
2550 FrameStateBeforeAndAfter states(
2551 this, args->is_empty() ? expr->expression()->id() : args->last()->id());
2552
2553 // The new target is the same as the callee.
2554 environment()->Push(environment()->Peek(args->length()));
2555
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556 // Create node to perform the construct call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002557 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2558 const Operator* call =
2559 javascript()->CallConstruct(args->length() + 2, feedback);
2560 Node* value = ProcessArguments(call, args->length() + 2);
2561 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002562 ast_context()->ProduceValue(value);
2563}
2564
2565
2566void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002567 // The callee and the receiver both have to be pushed onto the operand stack
2568 // before arguments are being evaluated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002569 Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2570 Node* receiver_value = jsgraph()->UndefinedConstant();
2571
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002572 environment()->Push(callee_value);
2573 environment()->Push(receiver_value);
2574
2575 // Evaluate all arguments to the JS runtime call.
2576 ZoneList<Expression*>* args = expr->arguments();
2577 VisitForValues(args);
2578
2579 // Create node to perform the JS runtime call.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002580 const Operator* call = javascript()->CallFunction(args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002581 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002582 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002583 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002584 ast_context()->ProduceValue(value);
2585}
2586
2587
2588void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002589 // Handle calls to runtime functions implemented in JavaScript separately as
2590 // the call follows JavaScript ABI and the callee is statically unknown.
2591 if (expr->is_jsruntime()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002592 return VisitCallJSRuntime(expr);
2593 }
2594
2595 // Evaluate all arguments to the runtime call.
2596 ZoneList<Expression*>* args = expr->arguments();
2597 VisitForValues(args);
2598
2599 // Create node to perform the runtime call.
Ben Murdochda12d292016-06-02 14:46:10 +01002600 Runtime::FunctionId functionId = expr->function()->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002601 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603 Node* value = ProcessArguments(call, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002604 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002605 ast_context()->ProduceValue(value);
2606}
2607
2608
2609void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2610 switch (expr->op()) {
2611 case Token::DELETE:
2612 return VisitDelete(expr);
2613 case Token::VOID:
2614 return VisitVoid(expr);
2615 case Token::TYPEOF:
2616 return VisitTypeof(expr);
2617 case Token::NOT:
2618 return VisitNot(expr);
2619 default:
2620 UNREACHABLE();
2621 }
2622}
2623
2624
2625void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627
2628 // Left-hand side can only be a property, a global or a variable slot.
2629 Property* property = expr->expression()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002630 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002631
2632 // Reserve space for result of postfix operation.
2633 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002634 if (is_postfix && assign_type != VARIABLE) {
2635 environment()->Push(jsgraph()->ZeroConstant());
2636 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002637
2638 // Evaluate LHS expression and get old value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002639 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002640 int stack_depth = -1;
2641 switch (assign_type) {
2642 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002643 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2644 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002645 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002646 old_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002647 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2648 pair, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002649 stack_depth = 0;
2650 break;
2651 }
2652 case NAMED_PROPERTY: {
2653 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002654 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002655 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002656 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002657 VectorSlotPair pair =
2658 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002659 old_value = BuildNamedLoad(object, name, pair);
2660 states.AddToNode(old_value, property->LoadId(),
2661 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002662 stack_depth = 1;
2663 break;
2664 }
2665 case KEYED_PROPERTY: {
2666 VisitForValue(property->obj());
2667 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002668 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002669 Node* key = environment()->Top();
2670 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002671 VectorSlotPair pair =
2672 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002673 old_value = BuildKeyedLoad(object, key, pair);
2674 states.AddToNode(old_value, property->LoadId(),
2675 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002676 stack_depth = 2;
2677 break;
2678 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002679 case NAMED_SUPER_PROPERTY: {
2680 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2681 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2682 FrameStateBeforeAndAfter states(this, property->obj()->id());
2683 Node* home_object = environment()->Top();
2684 Node* receiver = environment()->Peek(1);
2685 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2686 VectorSlotPair pair =
2687 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2688 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2689 states.AddToNode(old_value, property->LoadId(),
2690 OutputFrameStateCombine::Push());
2691 stack_depth = 2;
2692 break;
2693 }
2694 case KEYED_SUPER_PROPERTY: {
2695 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2696 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2697 VisitForValue(property->key());
2698 FrameStateBeforeAndAfter states(this, property->obj()->id());
2699 Node* key = environment()->Top();
2700 Node* home_object = environment()->Peek(1);
2701 Node* receiver = environment()->Peek(2);
2702 VectorSlotPair pair =
2703 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2704 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2705 states.AddToNode(old_value, property->LoadId(),
2706 OutputFrameStateCombine::Push());
2707 stack_depth = 3;
2708 break;
2709 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002710 }
2711
2712 // Convert old value into a number.
Ben Murdochda12d292016-06-02 14:46:10 +01002713 old_value = NewNode(javascript()->ToNumber(), old_value);
2714 PrepareFrameState(old_value, expr->ToNumberId(),
2715 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002716
2717 // Create a proper eager frame state for the stores.
2718 environment()->Push(old_value);
2719 FrameStateBeforeAndAfter store_states(this, expr->ToNumberId());
2720 old_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002721
2722 // Save result for postfix expressions at correct stack depth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002723 if (is_postfix) {
2724 if (assign_type != VARIABLE) {
2725 environment()->Poke(stack_depth, old_value);
2726 } else {
2727 environment()->Push(old_value);
2728 }
2729 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002730
2731 // Create node to perform +1/-1 operation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002732 Node* value;
2733 {
2734 // TODO(bmeurer): Cleanup this feedback/bailout mess!
2735 FrameStateBeforeAndAfter states(this, BailoutId::None());
2736 value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002737 expr->binary_op(), expr->CountBinOpFeedbackId());
Ben Murdochda12d292016-06-02 14:46:10 +01002738 // This should never deoptimize because we have converted to number before.
2739 states.AddToNode(value, BailoutId::None(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002740 OutputFrameStateCombine::Ignore());
2741 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002742
2743 // Store the value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002744 VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002745 switch (assign_type) {
2746 case VARIABLE: {
2747 Variable* variable = expr->expression()->AsVariableProxy()->var();
2748 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 BuildVariableAssignment(variable, value, expr->op(), feedback,
2750 expr->AssignmentId(), store_states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002751 environment()->Pop();
2752 break;
2753 }
2754 case NAMED_PROPERTY: {
2755 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002756 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2757 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002759 store_states.AddToNode(store, expr->AssignmentId(),
2760 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002761 environment()->Pop();
2762 break;
2763 }
2764 case KEYED_PROPERTY: {
2765 Node* key = environment()->Pop();
2766 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002767 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002768 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002769 store_states.AddToNode(store, expr->AssignmentId(),
2770 OutputFrameStateCombine::Ignore());
2771 environment()->Pop();
2772 break;
2773 }
2774 case NAMED_SUPER_PROPERTY: {
2775 Node* home_object = environment()->Pop();
2776 Node* receiver = environment()->Pop();
2777 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2778 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2779 environment()->Push(value);
2780 store_states.AddToNode(store, expr->AssignmentId(),
2781 OutputFrameStateCombine::Ignore());
2782 environment()->Pop();
2783 break;
2784 }
2785 case KEYED_SUPER_PROPERTY: {
2786 Node* key = environment()->Pop();
2787 Node* home_object = environment()->Pop();
2788 Node* receiver = environment()->Pop();
2789 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2790 environment()->Push(value);
2791 store_states.AddToNode(store, expr->AssignmentId(),
2792 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002793 environment()->Pop();
2794 break;
2795 }
2796 }
2797
2798 // Restore old value for postfix expressions.
2799 if (is_postfix) value = environment()->Pop();
2800
2801 ast_context()->ProduceValue(value);
2802}
2803
2804
2805void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2806 switch (expr->op()) {
2807 case Token::COMMA:
2808 return VisitComma(expr);
2809 case Token::OR:
2810 case Token::AND:
2811 return VisitLogicalExpression(expr);
2812 default: {
2813 VisitForValue(expr->left());
2814 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002815 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002816 Node* right = environment()->Pop();
2817 Node* left = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002818 Node* value = BuildBinaryOp(left, right, expr->op(),
2819 expr->BinaryOperationFeedbackId());
2820 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002821 ast_context()->ProduceValue(value);
2822 }
2823 }
2824}
2825
Ben Murdochda12d292016-06-02 14:46:10 +01002826void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
2827 Expression* sub_expr,
2828 Node* nil_value) {
2829 const Operator* op = nullptr;
2830 switch (expr->op()) {
2831 case Token::EQ:
2832 op = javascript()->Equal();
2833 break;
2834 case Token::EQ_STRICT:
2835 op = javascript()->StrictEqual();
2836 break;
2837 default:
2838 UNREACHABLE();
2839 }
2840 VisitForValue(sub_expr);
2841 FrameStateBeforeAndAfter states(this, sub_expr->id());
2842 Node* value_to_compare = environment()->Pop();
2843 Node* value = NewNode(op, value_to_compare, nil_value);
2844 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2845 return ast_context()->ProduceValue(value);
2846}
2847
2848void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
2849 Expression* sub_expr,
2850 Handle<String> check) {
2851 VisitTypeofExpression(sub_expr);
2852 FrameStateBeforeAndAfter states(this, sub_expr->id());
2853 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
2854 Node* value = NewNode(javascript()->StrictEqual(), typeof_arg,
2855 jsgraph()->Constant(check));
2856 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2857 return ast_context()->ProduceValue(value);
2858}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002859
2860void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Ben Murdochda12d292016-06-02 14:46:10 +01002861 // Check for a few fast cases. The AST visiting behavior must be in sync
2862 // with the full codegen: We don't push both left and right values onto
2863 // the expression stack when one side is a special-case literal.
2864 Expression* sub_expr = nullptr;
2865 Handle<String> check;
2866 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
2867 return VisitLiteralCompareTypeof(expr, sub_expr, check);
2868 }
2869 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
2870 return VisitLiteralCompareNil(expr, sub_expr,
2871 jsgraph()->UndefinedConstant());
2872 }
2873 if (expr->IsLiteralCompareNull(&sub_expr)) {
2874 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
2875 }
2876
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002877 const Operator* op;
2878 switch (expr->op()) {
2879 case Token::EQ:
2880 op = javascript()->Equal();
2881 break;
2882 case Token::NE:
2883 op = javascript()->NotEqual();
2884 break;
2885 case Token::EQ_STRICT:
2886 op = javascript()->StrictEqual();
2887 break;
2888 case Token::NE_STRICT:
2889 op = javascript()->StrictNotEqual();
2890 break;
2891 case Token::LT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002892 op = javascript()->LessThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002893 break;
2894 case Token::GT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002895 op = javascript()->GreaterThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002896 break;
2897 case Token::LTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002898 op = javascript()->LessThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002899 break;
2900 case Token::GTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002901 op = javascript()->GreaterThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002902 break;
2903 case Token::INSTANCEOF:
2904 op = javascript()->InstanceOf();
2905 break;
2906 case Token::IN:
2907 op = javascript()->HasProperty();
2908 break;
2909 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002910 op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002911 UNREACHABLE();
2912 }
2913 VisitForValue(expr->left());
2914 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002915 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002916 Node* right = environment()->Pop();
2917 Node* left = environment()->Pop();
2918 Node* value = NewNode(op, left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002919 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002920 ast_context()->ProduceValue(value);
2921}
2922
2923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002924void AstGraphBuilder::VisitSpread(Spread* expr) {
2925 // Handled entirely by the parser itself.
2926 UNREACHABLE();
2927}
2928
2929
2930void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2931 // Handled entirely by the parser itself.
2932 UNREACHABLE();
2933}
2934
2935
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002936void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2937 Node* value = GetFunctionClosure();
2938 ast_context()->ProduceValue(value);
2939}
2940
2941
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002942void AstGraphBuilder::VisitSuperPropertyReference(
2943 SuperPropertyReference* expr) {
2944 Node* value = BuildThrowUnsupportedSuperError(expr->id());
2945 ast_context()->ProduceValue(value);
2946}
2947
2948
2949void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2950 // Handled by VisitCall
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002951 UNREACHABLE();
2952}
2953
2954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002955void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2956 // Handled entirely in VisitSwitch.
2957 UNREACHABLE();
2958}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002959
2960
2961void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002962 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002963 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002964 if (globals()->empty()) return;
2965 int array_index = 0;
2966 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2967 static_cast<int>(globals()->size()), TENURED);
2968 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochc5610432016-08-08 18:44:38 +01002969 int encoded_flags = info()->GetDeclareGlobalsFlags();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002970 Node* flags = jsgraph()->Constant(encoded_flags);
2971 Node* pairs = jsgraph()->Constant(data);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002972 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002973 Node* call = NewNode(op, pairs, flags);
2974 PrepareFrameState(call, BailoutId::Declarations());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002975 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002976}
2977
2978
2979void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002980 if (stmt == nullptr) return;
2981 Visit(stmt);
2982}
2983
2984
2985void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2986 ContextScope scope(this, s, context);
2987 DCHECK(s->declarations()->is_empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002988 Visit(stmt);
2989}
2990
2991
2992void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002993 LoopBuilder* loop) {
2994 ControlScopeForIteration scope(this, stmt, loop);
2995 if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
2996 Node* node = NewNode(javascript()->StackCheck());
2997 PrepareFrameState(node, stmt->StackCheckId());
2998 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002999 Visit(stmt->body());
3000}
3001
3002
3003void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
3004 Node* value;
3005 if (expr->expression()->IsVariableProxy()) {
3006 // Delete of an unqualified identifier is only allowed in classic mode but
3007 // deleting "this" is allowed in all language modes.
3008 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003009 // Delete of an unqualified identifier is disallowed in strict mode but
3010 // "delete this" is allowed.
3011 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003012 value = BuildVariableDelete(variable, expr->id(),
3013 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003014 } else if (expr->expression()->IsProperty()) {
3015 Property* property = expr->expression()->AsProperty();
3016 VisitForValue(property->obj());
3017 VisitForValue(property->key());
3018 Node* key = environment()->Pop();
3019 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003020 value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003021 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003022 } else {
3023 VisitForEffect(expr->expression());
3024 value = jsgraph()->TrueConstant();
3025 }
3026 ast_context()->ProduceValue(value);
3027}
3028
3029
3030void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
3031 VisitForEffect(expr->expression());
3032 Node* value = jsgraph()->UndefinedConstant();
3033 ast_context()->ProduceValue(value);
3034}
3035
Ben Murdochda12d292016-06-02 14:46:10 +01003036void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
3037 if (expr->IsVariableProxy()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003038 // Typeof does not throw a reference error on global variables, hence we
3039 // perform a non-contextual load in case the operand is a variable proxy.
Ben Murdochda12d292016-06-02 14:46:10 +01003040 VariableProxy* proxy = expr->AsVariableProxy();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003041 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003042 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Ben Murdochda12d292016-06-02 14:46:10 +01003043 Node* load =
3044 BuildVariableLoad(proxy->var(), expr->id(), states, pair,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003045 OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Ben Murdochda12d292016-06-02 14:46:10 +01003046 environment()->Push(load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003047 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01003048 VisitForValue(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003049 }
Ben Murdochda12d292016-06-02 14:46:10 +01003050}
3051
3052void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
3053 VisitTypeofExpression(expr->expression());
3054 Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003055 ast_context()->ProduceValue(value);
3056}
3057
3058
3059void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3060 VisitForValue(expr->expression());
3061 Node* operand = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003062 Node* input = BuildToBoolean(operand, expr->expression()->test_id());
3063 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
3064 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003065 ast_context()->ProduceValue(value);
3066}
3067
3068
3069void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3070 VisitForEffect(expr->left());
3071 Visit(expr->right());
3072 ast_context()->ReplaceValue();
3073}
3074
3075
3076void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3077 bool is_logical_and = expr->op() == Token::AND;
3078 IfBuilder compare_if(this);
3079 VisitForValue(expr->left());
3080 Node* condition = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003081 compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003082 compare_if.Then();
3083 if (is_logical_and) {
3084 environment()->Pop();
3085 Visit(expr->right());
3086 } else if (ast_context()->IsEffect()) {
3087 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003088 } else if (ast_context()->IsTest()) {
3089 environment()->Poke(0, jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003090 }
3091 compare_if.Else();
3092 if (!is_logical_and) {
3093 environment()->Pop();
3094 Visit(expr->right());
3095 } else if (ast_context()->IsEffect()) {
3096 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003097 } else if (ast_context()->IsTest()) {
3098 environment()->Poke(0, jsgraph()->FalseConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003099 }
3100 compare_if.End();
3101 ast_context()->ReplaceValue();
3102}
3103
3104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003105LanguageMode AstGraphBuilder::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003106 return current_scope()->language_mode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003107}
3108
3109
3110VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003111 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003112 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3113}
3114
3115
Ben Murdoch097c5b22016-05-18 11:27:45 +01003116void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003117 Visit(node->expression());
3118}
3119
3120
3121namespace {
3122
3123// Limit of context chain length to which inline check is possible.
3124const int kMaxCheckDepth = 30;
3125
3126// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3127const uint32_t kFullCheckRequired = -1;
3128
3129} // namespace
3130
3131
3132uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3133 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3134 bool found_eval_scope = false;
3135 uint32_t check_depths = 0;
3136 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3137 if (s->num_heap_slots() <= 0) continue;
3138 // TODO(mstarzinger): If we have reached an eval scope, we check all
3139 // extensions from this point. Replicated from full-codegen, figure out
3140 // whether this is still needed. If not, drop {found_eval_scope} below.
3141 if (s->is_eval_scope()) found_eval_scope = true;
3142 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3143 int depth = current_scope()->ContextChainLength(s);
3144 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3145 check_depths |= 1 << depth;
3146 }
3147 return check_depths;
3148}
3149
3150
3151uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3152 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3153 uint32_t check_depths = 0;
3154 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3155 if (s->num_heap_slots() <= 0) continue;
3156 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3157 int depth = current_scope()->ContextChainLength(s);
3158 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3159 check_depths |= 1 << depth;
3160 if (s == variable->scope()) break;
3161 }
3162 return check_depths;
3163}
3164
3165
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003166Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3167 DCHECK(environment()->stack_height() >= arity);
3168 Node** all = info()->zone()->NewArray<Node*>(arity);
3169 for (int i = arity - 1; i >= 0; --i) {
3170 all[i] = environment()->Pop();
3171 }
3172 Node* value = NewNode(op, arity, all);
3173 return value;
3174}
3175
3176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003177Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3178 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003179
3180 // Allocate a new local context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003181 Node* local_context = scope->is_script_scope()
3182 ? BuildLocalScriptContext(scope)
3183 : BuildLocalFunctionContext(scope);
3184
3185 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3186 Node* receiver = environment()->RawParameterLookup(0);
3187 // Context variable (at bottom of the context chain).
3188 Variable* variable = scope->receiver();
3189 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3190 const Operator* op = javascript()->StoreContext(0, variable->index());
3191 NewNode(op, local_context, receiver);
3192 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003193
3194 // Copy parameters into context if necessary.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003195 int num_parameters = scope->num_parameters();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003196 for (int i = 0; i < num_parameters; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003197 Variable* variable = scope->parameter(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003198 if (!variable->IsContextSlot()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003199 Node* parameter = environment()->RawParameterLookup(i + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003200 // Context variable (at bottom of the context chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003201 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003202 const Operator* op = javascript()->StoreContext(0, variable->index());
3203 NewNode(op, local_context, parameter);
3204 }
3205
3206 return local_context;
3207}
3208
3209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003210Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
Ben Murdochc5610432016-08-08 18:44:38 +01003211 DCHECK(scope->is_function_scope() || scope->is_eval_scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003212
3213 // Allocate a new local context.
3214 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3215 const Operator* op = javascript()->CreateFunctionContext(slot_count);
3216 Node* local_context = NewNode(op, GetFunctionClosure());
3217
3218 return local_context;
3219}
3220
3221
3222Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3223 DCHECK(scope->is_script_scope());
3224
3225 // Allocate a new local context.
3226 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3227 const Operator* op = javascript()->CreateScriptContext(scope_info);
3228 Node* local_context = NewNode(op, GetFunctionClosure());
3229 PrepareFrameState(local_context, BailoutId::ScriptContext(),
3230 OutputFrameStateCombine::Push());
3231
3232 return local_context;
3233}
3234
3235
3236Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3237 DCHECK(scope->is_block_scope());
3238
3239 // Allocate a new local context.
3240 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3241 const Operator* op = javascript()->CreateBlockContext(scope_info);
3242 Node* local_context = NewNode(op, GetFunctionClosureForContext());
3243
3244 return local_context;
3245}
3246
3247
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003248Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003249 if (arguments == nullptr) return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003250
3251 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003252 CreateArgumentsType type =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003253 is_strict(language_mode()) || !info()->has_simple_parameters()
Ben Murdoch097c5b22016-05-18 11:27:45 +01003254 ? CreateArgumentsType::kUnmappedArguments
3255 : CreateArgumentsType::kMappedArguments;
3256 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003257 Node* object = NewNode(op, GetFunctionClosure());
3258 PrepareFrameState(object, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003259
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003260 // Assign the object to the {arguments} variable. This should never lazy
3261 // deopt, so it is fine to send invalid bailout id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003262 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003263 FrameStateBeforeAndAfter states(this, BailoutId::None());
3264 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3265 BailoutId::None(), states);
3266 return object;
3267}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003269
3270Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3271 if (rest == nullptr) return nullptr;
3272
3273 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003274 CreateArgumentsType type = CreateArgumentsType::kRestParameter;
3275 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003276 Node* object = NewNode(op, GetFunctionClosure());
3277 PrepareFrameState(object, BailoutId::None());
3278
3279 // Assign the object to the {rest} variable. This should never lazy
3280 // deopt, so it is fine to send invalid bailout id.
3281 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3282 FrameStateBeforeAndAfter states(this, BailoutId::None());
3283 BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3284 BailoutId::None(), states);
3285 return object;
3286}
3287
3288
3289Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3290 if (this_function_var == nullptr) return nullptr;
3291
3292 // Retrieve the closure we were called with.
3293 Node* this_function = GetFunctionClosure();
3294
3295 // Assign the object to the {.this_function} variable. This should never lazy
3296 // deopt, so it is fine to send invalid bailout id.
3297 FrameStateBeforeAndAfter states(this, BailoutId::None());
3298 BuildVariableAssignment(this_function_var, this_function, Token::INIT,
3299 VectorSlotPair(), BailoutId::None(), states);
3300 return this_function;
3301}
3302
3303
3304Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3305 if (new_target_var == nullptr) return nullptr;
3306
3307 // Retrieve the new target we were called with.
3308 Node* object = GetNewTarget();
3309
3310 // Assign the object to the {new.target} variable. This should never lazy
3311 // deopt, so it is fine to send invalid bailout id.
3312 FrameStateBeforeAndAfter states(this, BailoutId::None());
3313 BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
3314 BailoutId::None(), states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003315 return object;
3316}
3317
3318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003319Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3320 Node* not_hole,
3321 BailoutId bailout_id) {
3322 IfBuilder hole_check(this);
3323 Node* the_hole = jsgraph()->TheHoleConstant();
3324 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3325 hole_check.If(check);
3326 hole_check.Then();
3327 Node* error = BuildThrowReferenceError(variable, bailout_id);
3328 environment()->Push(error);
3329 hole_check.Else();
3330 environment()->Push(not_hole);
3331 hole_check.End();
3332 return environment()->Pop();
3333}
3334
3335
3336Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3337 Node* for_hole,
3338 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003339 IfBuilder hole_check(this);
3340 Node* the_hole = jsgraph()->TheHoleConstant();
3341 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3342 hole_check.If(check);
3343 hole_check.Then();
3344 environment()->Push(for_hole);
3345 hole_check.Else();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003346 Node* error = BuildThrowReferenceError(variable, bailout_id);
3347 environment()->Push(error);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003348 hole_check.End();
3349 return environment()->Pop();
3350}
3351
3352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003353Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3354 BailoutId bailout_id) {
3355 IfBuilder prototype_check(this);
3356 Node* prototype_string =
3357 jsgraph()->Constant(isolate()->factory()->prototype_string());
3358 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
3359 prototype_check.If(check);
3360 prototype_check.Then();
3361 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3362 environment()->Push(error);
3363 prototype_check.Else();
3364 environment()->Push(name);
3365 prototype_check.End();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003366 return environment()->Pop();
3367}
3368
3369
3370Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3371 BailoutId bailout_id,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003372 FrameStateBeforeAndAfter& states,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003373 const VectorSlotPair& feedback,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003374 OutputFrameStateCombine combine,
3375 TypeofMode typeof_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003376 Node* the_hole = jsgraph()->TheHoleConstant();
3377 VariableMode mode = variable->mode();
3378 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003379 case VariableLocation::GLOBAL:
3380 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003381 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003382 Handle<Name> name = variable->name();
3383 if (Node* node = TryLoadGlobalConstant(name)) return node;
3384 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
3385 states.AddToNode(value, bailout_id, combine);
3386 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003387 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003388 case VariableLocation::PARAMETER:
3389 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003390 // Local var, const, or let variable.
3391 Node* value = environment()->Lookup(variable);
Ben Murdochc5610432016-08-08 18:44:38 +01003392 if (mode == LET || mode == CONST) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003393 // Perform check for uninitialized let/const variables.
3394 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003395 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003396 } else if (value->opcode() == IrOpcode::kPhi) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003397 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003398 }
3399 }
3400 return value;
3401 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003402 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003403 // Context variable (potentially up the context chain).
3404 int depth = current_scope()->ContextChainLength(variable->scope());
3405 bool immutable = variable->maybe_assigned() == kNotAssigned;
3406 const Operator* op =
3407 javascript()->LoadContext(depth, variable->index(), immutable);
3408 Node* value = NewNode(op, current_context());
3409 // TODO(titzer): initialization checks are redundant for already
3410 // initialized immutable context loads, but only specialization knows.
3411 // Maybe specializer should be a parameter to the graph builder?
Ben Murdochc5610432016-08-08 18:44:38 +01003412 if (mode == LET || mode == CONST) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003413 // Perform check for uninitialized let/const variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003414 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003415 }
3416 return value;
3417 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003418 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003419 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003420 Handle<String> name = variable->name();
3421 if (Node* node =
3422 TryLoadDynamicVariable(variable, name, bailout_id, states,
3423 feedback, combine, typeof_mode)) {
3424 return node;
3425 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003426 Node* value = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003427 states.AddToNode(value, bailout_id, combine);
3428 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003429 }
3430 }
3431 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003432 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003433}
3434
3435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003436Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3437 BailoutId bailout_id,
3438 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003439 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003440 case VariableLocation::GLOBAL:
3441 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003442 // Global var, const, or let variable.
3443 Node* global = BuildLoadGlobalObject();
3444 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003445 const Operator* op = javascript()->DeleteProperty(language_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003446 Node* result = NewNode(op, global, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003447 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003448 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003449 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003450 case VariableLocation::PARAMETER:
3451 case VariableLocation::LOCAL:
3452 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003453 // Local var, const, or let variable or context variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003454 return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3455 }
3456 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003457 // Dynamic lookup of context variable (anywhere in the chain).
3458 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003459 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003460 javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
3461 Node* result = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003462 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003463 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003464 }
3465 }
3466 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003467 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003468}
3469
3470
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003471Node* AstGraphBuilder::BuildVariableAssignment(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003472 Variable* variable, Node* value, Token::Value op,
3473 const VectorSlotPair& feedback, BailoutId bailout_id,
3474 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003475 Node* the_hole = jsgraph()->TheHoleConstant();
3476 VariableMode mode = variable->mode();
3477 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003478 case VariableLocation::GLOBAL:
3479 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003480 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003481 Handle<Name> name = variable->name();
3482 Node* store = BuildGlobalStore(name, value, feedback);
3483 states.AddToNode(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003484 return store;
3485 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003486 case VariableLocation::PARAMETER:
3487 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003488 // Local var, const, or let variable.
Ben Murdochc5610432016-08-08 18:44:38 +01003489 if (mode == CONST_LEGACY && op != Token::INIT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003490 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003491 // - exception in strict mode.
3492 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003493 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003494 return BuildThrowConstAssignError(bailout_id);
3495 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003496 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003497 } else if (mode == LET && op == Token::INIT) {
3498 // No initialization check needed because scoping guarantees it. Note
3499 // that we still perform a lookup to keep the variable live, because
3500 // baseline code might contain debug code that inspects the variable.
3501 Node* current = environment()->Lookup(variable);
3502 CHECK_NOT_NULL(current);
3503 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003504 // Perform an initialization check for let declared variables.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003505 Node* current = environment()->Lookup(variable);
3506 if (current->op() == the_hole->op()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003507 return BuildThrowReferenceError(variable, bailout_id);
3508 } else if (current->opcode() == IrOpcode::kPhi) {
3509 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003510 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003511 } else if (mode == CONST && op == Token::INIT) {
3512 // Perform an initialization check for const {this} variables.
3513 // Note that the {this} variable is the only const variable being able
3514 // to trigger bind operations outside the TDZ, via {super} calls.
3515 Node* current = environment()->Lookup(variable);
3516 if (current->op() != the_hole->op() && variable->is_this()) {
3517 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3518 }
3519 } else if (mode == CONST && op != Token::INIT) {
3520 // Assignment to const is exception in all modes.
3521 Node* current = environment()->Lookup(variable);
3522 if (current->op() == the_hole->op()) {
3523 return BuildThrowReferenceError(variable, bailout_id);
3524 } else if (current->opcode() == IrOpcode::kPhi) {
3525 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3526 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003527 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003528 }
3529 environment()->Bind(variable, value);
3530 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003531 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003532 // Context variable (potentially up the context chain).
3533 int depth = current_scope()->ContextChainLength(variable->scope());
Ben Murdochc5610432016-08-08 18:44:38 +01003534 if (mode == CONST_LEGACY && op != Token::INIT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003535 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003536 // - exception in strict mode.
3537 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003538 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003539 return BuildThrowConstAssignError(bailout_id);
3540 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003541 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003542 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003543 // Perform an initialization check for let declared variables.
3544 const Operator* op =
3545 javascript()->LoadContext(depth, variable->index(), false);
3546 Node* current = NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003547 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3548 } else if (mode == CONST && op == Token::INIT) {
3549 // Perform an initialization check for const {this} variables.
3550 // Note that the {this} variable is the only const variable being able
3551 // to trigger bind operations outside the TDZ, via {super} calls.
3552 if (variable->is_this()) {
3553 const Operator* op =
3554 javascript()->LoadContext(depth, variable->index(), false);
3555 Node* current = NewNode(op, current_context());
3556 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3557 }
3558 } else if (mode == CONST && op != Token::INIT) {
3559 // Assignment to const is exception in all modes.
3560 const Operator* op =
3561 javascript()->LoadContext(depth, variable->index(), false);
3562 Node* current = NewNode(op, current_context());
3563 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003564 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003565 }
3566 const Operator* op = javascript()->StoreContext(depth, variable->index());
3567 return NewNode(op, current_context(), value);
3568 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003569 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003570 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch097c5b22016-05-18 11:27:45 +01003571 Handle<Name> name = variable->name();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003572 Node* store = BuildDynamicStore(name, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003573 PrepareFrameState(store, bailout_id, combine);
3574 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003575 }
3576 }
3577 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003578 return nullptr;
3579}
3580
3581
3582Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3583 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003584 const Operator* op = javascript()->LoadProperty(feedback);
3585 Node* node = NewNode(op, object, key, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003586 return node;
3587}
3588
3589
3590Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3591 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003592 const Operator* op = javascript()->LoadNamed(name, feedback);
3593 Node* node = NewNode(op, object, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003594 return node;
3595}
3596
3597
3598Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3599 const VectorSlotPair& feedback) {
3600 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003601 Node* node = NewNode(op, object, key, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003602 return node;
3603}
3604
3605
3606Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3607 Node* value,
3608 const VectorSlotPair& feedback) {
3609 const Operator* op =
3610 javascript()->StoreNamed(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003611 Node* node = NewNode(op, object, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003612 return node;
3613}
3614
3615
3616Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3617 Handle<Name> name,
3618 const VectorSlotPair& feedback) {
3619 Node* name_node = jsgraph()->Constant(name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003620 const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
3621 Node* node = NewNode(op, receiver, home_object, name_node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003622 return node;
3623}
3624
3625
3626Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3627 Node* key,
3628 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003629 const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
3630 Node* node = NewNode(op, receiver, home_object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003631 return node;
3632}
3633
3634
3635Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3636 Node* key, Node* value) {
3637 Runtime::FunctionId function_id = is_strict(language_mode())
3638 ? Runtime::kStoreKeyedToSuper_Strict
3639 : Runtime::kStoreKeyedToSuper_Sloppy;
3640 const Operator* op = javascript()->CallRuntime(function_id, 4);
3641 Node* node = NewNode(op, receiver, home_object, key, value);
3642 return node;
3643}
3644
3645
3646Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3647 Handle<Name> name, Node* value) {
3648 Node* name_node = jsgraph()->Constant(name);
3649 Runtime::FunctionId function_id = is_strict(language_mode())
3650 ? Runtime::kStoreToSuper_Strict
3651 : Runtime::kStoreToSuper_Sloppy;
3652 const Operator* op = javascript()->CallRuntime(function_id, 4);
3653 Node* node = NewNode(op, receiver, home_object, name_node, value);
3654 return node;
3655}
3656
3657
3658Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3659 const VectorSlotPair& feedback,
3660 TypeofMode typeof_mode) {
3661 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003662 Node* node = NewNode(op, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003663 return node;
3664}
3665
3666
3667Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3668 const VectorSlotPair& feedback) {
3669 const Operator* op =
3670 javascript()->StoreGlobal(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003671 Node* node = NewNode(op, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003672 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003673}
3674
3675
Ben Murdoch097c5b22016-05-18 11:27:45 +01003676Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
3677 TypeofMode typeof_mode) {
3678 Node* name_node = jsgraph()->Constant(name);
3679 const Operator* op =
3680 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
3681 ? Runtime::kLoadLookupSlot
3682 : Runtime::kLoadLookupSlotInsideTypeof);
3683 Node* node = NewNode(op, name_node);
3684 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003685}
3686
3687
Ben Murdoch097c5b22016-05-18 11:27:45 +01003688Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
3689 Node* name_node = jsgraph()->Constant(name);
3690 const Operator* op = javascript()->CallRuntime(
3691 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
3692 : Runtime::kStoreLookupSlot_Sloppy);
3693 Node* node = NewNode(op, name_node, value);
3694 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003695}
3696
3697
3698Node* AstGraphBuilder::BuildLoadGlobalObject() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003699 return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003700}
3701
3702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003703Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3704 const Operator* op =
3705 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3706 Node* native_context = NewNode(op, current_context());
3707 return NewNode(javascript()->LoadContext(0, index, true), native_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003708}
3709
3710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003711Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3712 if (Node* node = TryFastToBoolean(input)) return node;
3713 ToBooleanHints hints;
3714 if (!type_hint_analysis_ ||
3715 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3716 hints = ToBooleanHint::kAny;
3717 }
3718 return NewNode(javascript()->ToBoolean(hints), input);
3719}
3720
3721
3722Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3723 if (Node* node = TryFastToName(input)) return node;
3724 Node* name = NewNode(javascript()->ToName(), input);
3725 PrepareFrameState(name, bailout_id);
3726 return name;
3727}
3728
3729
3730Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3731 Node* object = NewNode(javascript()->ToObject(), input);
3732 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3733 return object;
3734}
3735
3736
3737Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3738 ObjectLiteralProperty* property,
3739 int slot_number) {
3740 Expression* expr = property->value();
3741 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3742 Handle<Name> name = isolate()->factory()->home_object_symbol();
3743 FrameStateBeforeAndAfter states(this, BailoutId::None());
3744 VectorSlotPair feedback =
3745 CreateVectorSlotPair(property->GetSlot(slot_number));
3746 Node* store = BuildNamedStore(value, name, home_object, feedback);
3747 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3748 return store;
3749}
3750
3751
3752Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003753 const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003754 Node* call = NewNode(op, exception);
3755 PrepareFrameState(call, bailout_id);
3756 Node* control = NewNode(common()->Throw(), call);
3757 UpdateControlDependencyToLeaveFunction(control);
3758 return call;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003759}
3760
3761
3762Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3763 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003764 Node* variable_name = jsgraph()->Constant(variable->name());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003765 const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003766 Node* call = NewNode(op, variable_name);
3767 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003768 Node* control = NewNode(common()->Throw(), call);
3769 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003770 return call;
3771}
3772
3773
3774Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003775 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003776 javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003777 Node* call = NewNode(op);
3778 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003779 Node* control = NewNode(common()->Throw(), call);
3780 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003781 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003782}
3783
3784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003785Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3786 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003787 javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003788 Node* call = NewNode(op);
3789 PrepareFrameState(call, bailout_id);
3790 Node* control = NewNode(common()->Throw(), call);
3791 UpdateControlDependencyToLeaveFunction(control);
3792 return call;
3793}
3794
3795
3796Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3797 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003798 javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003799 Node* call = NewNode(op);
3800 PrepareFrameState(call, bailout_id);
3801 Node* control = NewNode(common()->Throw(), call);
3802 UpdateControlDependencyToLeaveFunction(control);
3803 return call;
3804}
3805
3806
3807Node* AstGraphBuilder::BuildReturn(Node* return_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003808 // Emit tracing call if requested to do so.
3809 if (FLAG_trace) {
3810 return_value =
3811 NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
3812 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003813 Node* control = NewNode(common()->Return(), return_value);
3814 UpdateControlDependencyToLeaveFunction(control);
3815 return control;
3816}
3817
3818
3819Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003820 NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003821 Node* control = NewNode(common()->Throw(), exception_value);
3822 UpdateControlDependencyToLeaveFunction(control);
3823 return control;
3824}
3825
3826
3827Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3828 TypeFeedbackId feedback_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003829 const Operator* js_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003830 BinaryOperationHints hints;
3831 if (!type_hint_analysis_ ||
3832 !type_hint_analysis_->GetBinaryOperationHints(feedback_id, &hints)) {
3833 hints = BinaryOperationHints::Any();
3834 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003835 switch (op) {
3836 case Token::BIT_OR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003837 js_op = javascript()->BitwiseOr(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003838 break;
3839 case Token::BIT_AND:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003840 js_op = javascript()->BitwiseAnd(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003841 break;
3842 case Token::BIT_XOR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003843 js_op = javascript()->BitwiseXor(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003844 break;
3845 case Token::SHL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003846 js_op = javascript()->ShiftLeft(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003847 break;
3848 case Token::SAR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003849 js_op = javascript()->ShiftRight(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003850 break;
3851 case Token::SHR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003852 js_op = javascript()->ShiftRightLogical(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003853 break;
3854 case Token::ADD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003855 js_op = javascript()->Add(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003856 break;
3857 case Token::SUB:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003858 js_op = javascript()->Subtract(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003859 break;
3860 case Token::MUL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003861 js_op = javascript()->Multiply(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003862 break;
3863 case Token::DIV:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003864 js_op = javascript()->Divide(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003865 break;
3866 case Token::MOD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003867 js_op = javascript()->Modulus(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003868 break;
3869 default:
3870 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003871 js_op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003872 }
3873 return NewNode(js_op, left, right);
3874}
3875
3876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003877Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3878 // Optimize global constants like "undefined", "Infinity", and "NaN".
3879 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3880 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3881 return nullptr;
3882}
3883
3884
3885Node* AstGraphBuilder::TryLoadDynamicVariable(
3886 Variable* variable, Handle<String> name, BailoutId bailout_id,
3887 FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
3888 OutputFrameStateCombine combine, TypeofMode typeof_mode) {
3889 VariableMode mode = variable->mode();
3890
3891 if (mode == DYNAMIC_GLOBAL) {
3892 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3893 if (bitset == kFullCheckRequired) return nullptr;
3894
3895 // We are using two blocks to model fast and slow cases.
3896 BlockBuilder fast_block(this);
3897 BlockBuilder slow_block(this);
3898 environment()->Push(jsgraph()->TheHoleConstant());
3899 slow_block.BeginBlock();
3900 environment()->Pop();
3901 fast_block.BeginBlock();
3902
3903 // Perform checks whether the fast mode applies, by looking for any
3904 // extension object which might shadow the optimistic declaration.
3905 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3906 if ((bitset & 1) == 0) continue;
3907 Node* load = NewNode(
3908 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3909 current_context());
3910 Node* check = NewNode(javascript()->StrictEqual(), load,
3911 jsgraph()->TheHoleConstant());
3912 fast_block.BreakUnless(check, BranchHint::kTrue);
3913 }
3914
Ben Murdoch097c5b22016-05-18 11:27:45 +01003915 // Fast case, because variable is not shadowed.
3916 if (Node* constant = TryLoadGlobalConstant(name)) {
3917 environment()->Push(constant);
3918 } else {
3919 // Perform global slot load.
3920 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3921 states.AddToNode(fast, bailout_id, combine);
3922 environment()->Push(fast);
3923 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003924 slow_block.Break();
3925 environment()->Pop();
3926 fast_block.EndBlock();
3927
3928 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003929 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003930 states.AddToNode(slow, bailout_id, combine);
3931 environment()->Push(slow);
3932 slow_block.EndBlock();
3933
3934 return environment()->Pop();
3935 }
3936
3937 if (mode == DYNAMIC_LOCAL) {
3938 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3939 if (bitset == kFullCheckRequired) return nullptr;
3940
3941 // We are using two blocks to model fast and slow cases.
3942 BlockBuilder fast_block(this);
3943 BlockBuilder slow_block(this);
3944 environment()->Push(jsgraph()->TheHoleConstant());
3945 slow_block.BeginBlock();
3946 environment()->Pop();
3947 fast_block.BeginBlock();
3948
3949 // Perform checks whether the fast mode applies, by looking for any
3950 // extension object which might shadow the optimistic declaration.
3951 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3952 if ((bitset & 1) == 0) continue;
3953 Node* load = NewNode(
3954 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3955 current_context());
3956 Node* check = NewNode(javascript()->StrictEqual(), load,
3957 jsgraph()->TheHoleConstant());
3958 fast_block.BreakUnless(check, BranchHint::kTrue);
3959 }
3960
3961 // Fast case, because variable is not shadowed. Perform context slot load.
3962 Variable* local = variable->local_if_not_shadowed();
3963 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3964 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3965 typeof_mode);
3966 environment()->Push(fast);
3967 slow_block.Break();
3968 environment()->Pop();
3969 fast_block.EndBlock();
3970
3971 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003972 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003973 states.AddToNode(slow, bailout_id, combine);
3974 environment()->Push(slow);
3975 slow_block.EndBlock();
3976
3977 return environment()->Pop();
3978 }
3979
3980 return nullptr;
3981}
3982
3983
3984Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3985 switch (input->opcode()) {
3986 case IrOpcode::kNumberConstant: {
3987 NumberMatcher m(input);
3988 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3989 }
3990 case IrOpcode::kHeapConstant: {
3991 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3992 return jsgraph_->BooleanConstant(object->BooleanValue());
3993 }
3994 case IrOpcode::kJSEqual:
3995 case IrOpcode::kJSNotEqual:
3996 case IrOpcode::kJSStrictEqual:
3997 case IrOpcode::kJSStrictNotEqual:
3998 case IrOpcode::kJSLessThan:
3999 case IrOpcode::kJSLessThanOrEqual:
4000 case IrOpcode::kJSGreaterThan:
4001 case IrOpcode::kJSGreaterThanOrEqual:
4002 case IrOpcode::kJSToBoolean:
4003 case IrOpcode::kJSDeleteProperty:
4004 case IrOpcode::kJSHasProperty:
4005 case IrOpcode::kJSInstanceOf:
4006 return input;
4007 default:
4008 break;
4009 }
4010 return nullptr;
4011}
4012
4013
4014Node* AstGraphBuilder::TryFastToName(Node* input) {
4015 switch (input->opcode()) {
4016 case IrOpcode::kHeapConstant: {
4017 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4018 if (object->IsName()) return input;
4019 break;
4020 }
4021 case IrOpcode::kJSToString:
4022 case IrOpcode::kJSToName:
4023 case IrOpcode::kJSTypeOf:
4024 return input;
4025 default:
4026 break;
4027 }
4028 return nullptr;
4029}
4030
4031
4032bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4033 if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4034 info()->set_osr_expr_stack_height(std::max(
4035 environment()->stack_height(), info()->osr_expr_stack_height()));
4036 return true;
4037 }
4038 return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004039}
4040
4041
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004042void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4043 OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004044 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4045 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4046
4047 DCHECK_EQ(IrOpcode::kDead,
4048 NodeProperties::GetFrameStateInput(node, 0)->opcode());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004049 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004050 NodeProperties::ReplaceFrameStateInput(
Ben Murdoch097c5b22016-05-18 11:27:45 +01004051 node, 0,
4052 environment()->Checkpoint(ast_id, combine, node_has_exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004053 }
4054}
4055
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004056
4057BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4058 IterationStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004059 if (loop_assignment_analysis_ == nullptr) return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004060 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004061}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004062
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004063
4064Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4065 if (size > input_buffer_size_) {
4066 size = size + kInputBufferSizeIncrement + input_buffer_size_;
4067 input_buffer_ = local_zone()->NewArray<Node*>(size);
4068 input_buffer_size_ = size;
4069 }
4070 return input_buffer_;
4071}
4072
4073
4074Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4075 Node** value_inputs, bool incomplete) {
4076 DCHECK_EQ(op->ValueInputCount(), value_input_count);
4077
4078 bool has_context = OperatorProperties::HasContextInput(op);
4079 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4080 bool has_control = op->ControlInputCount() == 1;
4081 bool has_effect = op->EffectInputCount() == 1;
4082
4083 DCHECK(op->ControlInputCount() < 2);
4084 DCHECK(op->EffectInputCount() < 2);
4085
4086 Node* result = nullptr;
4087 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4088 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4089 } else {
4090 bool inside_try_scope = try_nesting_level_ > 0;
4091 int input_count_with_deps = value_input_count;
4092 if (has_context) ++input_count_with_deps;
4093 input_count_with_deps += frame_state_count;
4094 if (has_control) ++input_count_with_deps;
4095 if (has_effect) ++input_count_with_deps;
4096 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4097 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4098 Node** current_input = buffer + value_input_count;
4099 if (has_context) {
4100 *current_input++ = current_context();
4101 }
4102 for (int i = 0; i < frame_state_count; i++) {
4103 // The frame state will be inserted later. Here we misuse
4104 // the {Dead} node as a sentinel to be later overwritten
4105 // with the real frame state.
4106 *current_input++ = jsgraph()->Dead();
4107 }
4108 if (has_effect) {
4109 *current_input++ = environment_->GetEffectDependency();
4110 }
4111 if (has_control) {
4112 *current_input++ = environment_->GetControlDependency();
4113 }
4114 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4115 if (!environment()->IsMarkedAsUnreachable()) {
4116 // Update the current control dependency for control-producing nodes.
4117 if (NodeProperties::IsControl(result)) {
4118 environment_->UpdateControlDependency(result);
4119 }
4120 // Update the current effect dependency for effect-producing nodes.
4121 if (result->op()->EffectOutputCount() > 0) {
4122 environment_->UpdateEffectDependency(result);
4123 }
4124 // Add implicit exception continuation for throwing nodes.
4125 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4126 // Conservative prediction whether caught locally.
4127 IfExceptionHint hint = try_catch_nesting_level_ > 0
4128 ? IfExceptionHint::kLocallyCaught
4129 : IfExceptionHint::kLocallyUncaught;
4130 // Copy the environment for the success continuation.
4131 Environment* success_env = environment()->CopyForConditional();
4132 const Operator* op = common()->IfException(hint);
4133 Node* effect = environment()->GetEffectDependency();
4134 Node* on_exception = graph()->NewNode(op, effect, result);
4135 environment_->UpdateControlDependency(on_exception);
4136 environment_->UpdateEffectDependency(on_exception);
4137 execution_control()->ThrowValue(on_exception);
4138 set_environment(success_env);
4139 }
4140 // Add implicit success continuation for throwing nodes.
4141 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4142 const Operator* op = common()->IfSuccess();
4143 Node* on_success = graph()->NewNode(op, result);
4144 environment_->UpdateControlDependency(on_success);
4145 }
4146 }
4147 }
4148
4149 return result;
4150}
4151
4152
4153void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4154 if (environment()->IsMarkedAsUnreachable()) return;
4155 environment()->MarkAsUnreachable();
4156 exit_controls_.push_back(exit);
4157}
4158
4159
4160void AstGraphBuilder::Environment::Merge(Environment* other) {
4161 DCHECK(values_.size() == other->values_.size());
4162 DCHECK(contexts_.size() == other->contexts_.size());
4163
4164 // Nothing to do if the other environment is dead.
4165 if (other->IsMarkedAsUnreachable()) return;
4166
4167 // Resurrect a dead environment by copying the contents of the other one and
4168 // placing a singleton merge as the new control dependency.
4169 if (this->IsMarkedAsUnreachable()) {
4170 Node* other_control = other->control_dependency_;
4171 Node* inputs[] = {other_control};
4172 control_dependency_ =
4173 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4174 effect_dependency_ = other->effect_dependency_;
4175 values_ = other->values_;
4176 contexts_ = other->contexts_;
4177 if (IsLivenessAnalysisEnabled()) {
4178 liveness_block_ =
4179 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4180 }
4181 return;
4182 }
4183
4184 // Record the merge for the local variable liveness calculation.
4185 // For loops, we are connecting a back edge into the existing block;
4186 // for merges, we create a new merged block.
4187 if (IsLivenessAnalysisEnabled()) {
4188 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4189 liveness_block_ =
4190 builder_->liveness_analyzer()->NewBlock(liveness_block());
4191 }
4192 liveness_block()->AddPredecessor(other->liveness_block());
4193 }
4194
4195 // Create a merge of the control dependencies of both environments and update
4196 // the current environment's control dependency accordingly.
4197 Node* control = builder_->MergeControl(this->GetControlDependency(),
4198 other->GetControlDependency());
4199 UpdateControlDependency(control);
4200
4201 // Create a merge of the effect dependencies of both environments and update
4202 // the current environment's effect dependency accordingly.
4203 Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4204 other->GetEffectDependency(), control);
4205 UpdateEffectDependency(effect);
4206
4207 // Introduce Phi nodes for values that have differing input at merge points,
4208 // potentially extending an existing Phi node if possible.
4209 for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4210 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4211 }
4212 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4213 contexts_[i] =
4214 builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4215 }
4216}
4217
4218
4219void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4220 bool is_osr) {
4221 int size = static_cast<int>(values()->size());
4222
4223 Node* control = builder_->NewLoop();
4224 if (assigned == nullptr) {
4225 // Assume that everything is updated in the loop.
4226 for (int i = 0; i < size; ++i) {
4227 values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4228 }
4229 } else {
4230 // Only build phis for those locals assigned in this loop.
4231 for (int i = 0; i < size; ++i) {
4232 if (i < assigned->length() && !assigned->Contains(i)) continue;
4233 Node* phi = builder_->NewPhi(1, values()->at(i), control);
4234 values()->at(i) = phi;
4235 }
4236 }
4237 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4238 UpdateEffectDependency(effect);
4239
4240 // Connect the loop to end via Terminate if it's not marked as unreachable.
4241 if (!IsMarkedAsUnreachable()) {
4242 // Connect the Loop node to end via a Terminate node.
4243 Node* terminate = builder_->graph()->NewNode(
4244 builder_->common()->Terminate(), effect, control);
4245 builder_->exit_controls_.push_back(terminate);
4246 }
4247
4248 if (builder_->info()->is_osr()) {
4249 // Introduce phis for all context values in the case of an OSR graph.
4250 for (size_t i = 0; i < contexts()->size(); ++i) {
4251 Node* context = contexts()->at(i);
4252 contexts()->at(i) = builder_->NewPhi(1, context, control);
4253 }
4254 }
4255
4256 if (is_osr) {
4257 // Merge OSR values as inputs to the phis of the loop.
4258 Graph* graph = builder_->graph();
4259 Node* osr_loop_entry = builder_->graph()->NewNode(
4260 builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4261
4262 builder_->MergeControl(control, osr_loop_entry);
4263 builder_->MergeEffect(effect, osr_loop_entry, control);
4264
4265 for (int i = 0; i < size; ++i) {
4266 Node* value = values()->at(i);
4267 Node* osr_value =
4268 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4269 values()->at(i) = builder_->MergeValue(value, osr_value, control);
4270 }
4271
4272 // Rename all the contexts in the environment.
4273 // The innermost context is the OSR value, and the outer contexts are
4274 // reconstructed by dynamically walking up the context chain.
4275 Node* osr_context = nullptr;
4276 const Operator* op =
4277 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4278 const Operator* op_inner =
4279 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4280 int last = static_cast<int>(contexts()->size() - 1);
4281 for (int i = last; i >= 0; i--) {
4282 Node* context = contexts()->at(i);
4283 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4284 : graph->NewNode(op, osr_context, osr_context,
4285 osr_loop_entry);
4286 contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4287 }
4288 }
4289}
4290
4291
4292Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4293 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4294 Node** buffer = EnsureInputBufferSize(count + 1);
4295 MemsetPointer(buffer, input, count);
4296 buffer[count] = control;
4297 return graph()->NewNode(phi_op, count + 1, buffer, true);
4298}
4299
4300
4301// TODO(mstarzinger): Revisit this once we have proper effect states.
4302Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4303 const Operator* phi_op = common()->EffectPhi(count);
4304 Node** buffer = EnsureInputBufferSize(count + 1);
4305 MemsetPointer(buffer, input, count);
4306 buffer[count] = control;
4307 return graph()->NewNode(phi_op, count + 1, buffer, true);
4308}
4309
4310
4311Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4312 int inputs = control->op()->ControlInputCount() + 1;
4313 if (control->opcode() == IrOpcode::kLoop) {
4314 // Control node for loop exists, add input.
4315 const Operator* op = common()->Loop(inputs);
4316 control->AppendInput(graph_zone(), other);
4317 NodeProperties::ChangeOp(control, op);
4318 } else if (control->opcode() == IrOpcode::kMerge) {
4319 // Control node for merge exists, add input.
4320 const Operator* op = common()->Merge(inputs);
4321 control->AppendInput(graph_zone(), other);
4322 NodeProperties::ChangeOp(control, op);
4323 } else {
4324 // Control node is a singleton, introduce a merge.
4325 const Operator* op = common()->Merge(inputs);
4326 Node* inputs[] = {control, other};
4327 control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4328 }
4329 return control;
4330}
4331
4332
4333Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4334 int inputs = control->op()->ControlInputCount();
4335 if (value->opcode() == IrOpcode::kEffectPhi &&
4336 NodeProperties::GetControlInput(value) == control) {
4337 // Phi already exists, add input.
4338 value->InsertInput(graph_zone(), inputs - 1, other);
4339 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4340 } else if (value != other) {
4341 // Phi does not exist yet, introduce one.
4342 value = NewEffectPhi(inputs, value, control);
4343 value->ReplaceInput(inputs - 1, other);
4344 }
4345 return value;
4346}
4347
4348
4349Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4350 int inputs = control->op()->ControlInputCount();
4351 if (value->opcode() == IrOpcode::kPhi &&
4352 NodeProperties::GetControlInput(value) == control) {
4353 // Phi already exists, add input.
4354 value->InsertInput(graph_zone(), inputs - 1, other);
4355 NodeProperties::ChangeOp(
4356 value, common()->Phi(MachineRepresentation::kTagged, inputs));
4357 } else if (value != other) {
4358 // Phi does not exist yet, introduce one.
4359 value = NewPhi(inputs, value, control);
4360 value->ReplaceInput(inputs - 1, other);
4361 }
4362 return value;
4363}
4364
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004365} // namespace compiler
4366} // namespace internal
4367} // namespace v8