blob: d8d60f3388f89a05ac4380f58d720701ddf22ed4 [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) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100284 return owner_->NewNode(
285 owner_->javascript()->StrictEqual(CompareOperationHints::Any()), t1,
286 t2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 }
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()
Ben Murdoch61f157c2016-09-16 13:49:30 +0100419 ? builder_->GetEmptyFrameState()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 : builder_->environment()->Checkpoint(id_before);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100421 if (id_before != BailoutId::None()) {
422 // Create an explicit checkpoint node for before the operation.
423 Node* node = builder_->NewNode(builder_->common()->Checkpoint());
424 DCHECK_EQ(IrOpcode::kDead,
425 NodeProperties::GetFrameStateInput(node, 0)->opcode());
426 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_);
427 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 }
429
430 void AddToNode(
431 Node* node, BailoutId id_after,
432 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) {
433 int count = OperatorProperties::GetFrameStateInputCount(node->op());
434 DCHECK_LE(count, 2);
435
436 if (count >= 1) {
437 // Add the frame state for after the operation.
438 DCHECK_EQ(IrOpcode::kDead,
439 NodeProperties::GetFrameStateInput(node, 0)->opcode());
440
Ben Murdoch097c5b22016-05-18 11:27:45 +0100441 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 Node* frame_state_after =
444 id_after == BailoutId::None()
Ben Murdoch61f157c2016-09-16 13:49:30 +0100445 ? builder_->GetEmptyFrameState()
Ben Murdoch097c5b22016-05-18 11:27:45 +0100446 : builder_->environment()->Checkpoint(id_after, combine,
447 node_has_exception);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000448
449 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
450 }
451
452 if (count >= 2) {
453 // Add the frame state for before the operation.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100454 // TODO(mstarzinger): Get rid of frame state input before!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 DCHECK_EQ(IrOpcode::kDead,
456 NodeProperties::GetFrameStateInput(node, 1)->opcode());
457 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
458 }
459 }
460
461 private:
462 AstGraphBuilder* builder_;
463 Node* frame_state_before_;
464};
465
466
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400467AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
469 TypeHintAnalysis* type_hint_analysis)
470 : isolate_(info->isolate()),
471 local_zone_(local_zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 info_(info),
473 jsgraph_(jsgraph),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 environment_(nullptr),
475 ast_context_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476 globals_(0, local_zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 execution_control_(nullptr),
478 execution_context_(nullptr),
479 try_catch_nesting_level_(0),
480 try_nesting_level_(0),
481 input_buffer_size_(0),
482 input_buffer_(nullptr),
483 exit_controls_(local_zone),
484 loop_assignment_analysis_(loop),
485 type_hint_analysis_(type_hint_analysis),
486 state_values_cache_(jsgraph),
487 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
488 local_zone),
489 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
490 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100491 info->scope()->num_stack_slots(), info->shared_info())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 InitializeAstVisitor(info->isolate());
493}
494
495
496Node* AstGraphBuilder::GetFunctionClosureForContext() {
497 Scope* closure_scope = current_scope()->ClosureScope();
498 if (closure_scope->is_script_scope() ||
499 closure_scope->is_module_scope()) {
500 // Contexts nested in the native context have a canonical empty function as
501 // their closure, not the anonymous closure containing the global code.
502 return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
Ben Murdochc5610432016-08-08 18:44:38 +0100503 } else if (closure_scope->is_eval_scope()) {
504 // Contexts nested inside eval code have the same closure as the context
505 // calling eval, not the anonymous closure containing the eval code.
506 const Operator* op =
507 javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
508 return NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 } else {
510 DCHECK(closure_scope->is_function_scope());
511 return GetFunctionClosure();
512 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513}
514
515
516Node* AstGraphBuilder::GetFunctionClosure() {
517 if (!function_closure_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 int index = Linkage::kJSCallClosureParamIndex;
519 const Operator* op = common()->Parameter(index, "%closure");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 Node* node = NewNode(op, graph()->start());
521 function_closure_.set(node);
522 }
523 return function_closure_.get();
524}
525
526
527Node* AstGraphBuilder::GetFunctionContext() {
528 if (!function_context_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 int params = info()->num_parameters_including_this();
530 int index = Linkage::GetJSCallContextParamIndex(params);
531 const Operator* op = common()->Parameter(index, "%context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 Node* node = NewNode(op, graph()->start());
533 function_context_.set(node);
534 }
535 return function_context_.get();
536}
537
538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539Node* AstGraphBuilder::GetNewTarget() {
540 if (!new_target_.is_set()) {
541 int params = info()->num_parameters_including_this();
542 int index = Linkage::GetJSCallNewTargetParamIndex(params);
543 const Operator* op = common()->Parameter(index, "%new.target");
544 Node* node = NewNode(op, graph()->start());
545 new_target_.set(node);
546 }
547 return new_target_.get();
548}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549
Ben Murdoch61f157c2016-09-16 13:49:30 +0100550Node* AstGraphBuilder::GetEmptyFrameState() {
551 if (!empty_frame_state_.is_set()) {
552 const Operator* op = common()->FrameState(
553 BailoutId::None(), OutputFrameStateCombine::Ignore(), nullptr);
554 Node* node = graph()->NewNode(
555 op, jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
556 jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
557 jsgraph()->UndefinedConstant(), graph()->start());
558 empty_frame_state_.set(node);
559 }
560 return empty_frame_state_.get();
561}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562
563bool AstGraphBuilder::CreateGraph(bool stack_check) {
564 Scope* scope = info()->scope();
565 DCHECK_NOT_NULL(graph());
566
567 // Set up the basic structure of the graph. Outputs for {Start} are the formal
568 // parameters (including the receiver) plus new target, number of arguments,
569 // context and closure.
570 int actual_parameter_count = info()->num_parameters_including_this() + 4;
571 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572
573 // Initialize the top-level environment.
574 Environment env(this, scope, graph()->start());
575 set_environment(&env);
576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577 if (info()->is_osr()) {
578 // Use OSR normal entry as the start of the top-level environment.
579 // It will be replaced with {Dead} after typing and optimizations.
580 NewNode(common()->OsrNormalEntry());
581 }
582
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583 // Initialize the incoming context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 ContextScope incoming(this, scope, GetFunctionContext());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586 // Initialize control scope.
587 ControlScope control(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
590 // not {the_hole}, because for derived classes {this} has a TDZ and the
591 // JSConstructStubForDerived magically passes {the_hole} as a receiver.
592 if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
593 env.RawParameterBind(0, jsgraph()->TheHoleConstant());
594 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 // Build local context only if there are context allocated variables.
Ben Murdochc5610432016-08-08 18:44:38 +0100597 if (scope->num_heap_slots() > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 // Push a new inner context scope for the current activation.
599 Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
600 ContextScope top_context(this, scope, inner_context);
601 CreateGraphBody(stack_check);
602 } else {
603 // Simply use the outer function context in building the graph.
604 CreateGraphBody(stack_check);
605 }
606
607 // Finish the basic structure of the graph.
608 DCHECK_NE(0u, exit_controls_.size());
609 int const input_count = static_cast<int>(exit_controls_.size());
610 Node** const inputs = &exit_controls_.front();
611 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
612 graph()->SetEnd(end);
613
614 // Compute local variable liveness information and use it to relax
615 // frame states.
616 ClearNonLiveSlotsInFrameStates();
617
618 // Failures indicated by stack overflow.
619 return !HasStackOverflow();
620}
621
622
623void AstGraphBuilder::CreateGraphBody(bool stack_check) {
624 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625
626 // Build the arguments object if it is used.
627 BuildArgumentsObject(scope->arguments());
628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 // Build rest arguments array if it is used.
630 int rest_index;
631 Variable* rest_parameter = scope->rest_parameter(&rest_index);
632 BuildRestArgumentsArray(rest_parameter, rest_index);
633
634 // Build assignment to {.this_function} variable if it is used.
635 BuildThisFunctionVariable(scope->this_function_var());
636
637 // Build assignment to {new.target} variable if it is used.
638 BuildNewTargetVariable(scope->new_target_var());
639
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 // Emit tracing call if requested to do so.
641 if (FLAG_trace) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100642 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 }
644
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 // Visit declarations within the function scope.
646 VisitDeclarations(scope->declarations());
647
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400648 // Build a stack-check before the body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 if (stack_check) {
650 Node* node = NewNode(javascript()->StackCheck());
651 PrepareFrameState(node, BailoutId::FunctionEntry());
652 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653
654 // Visit statements in the function body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 VisitStatements(info()->literal()->body());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657 // Return 'undefined' in case we can fall off the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 BuildReturn(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659}
660
661
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
663 if (!FLAG_analyze_environment_liveness ||
664 !info()->is_deoptimization_enabled()) {
665 return;
666 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 NonLiveFrameStateSlotReplacer replacer(
Ben Murdochda12d292016-06-02 14:46:10 +0100669 &state_values_cache_, jsgraph()->OptimizedOutConstant(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 liveness_analyzer()->local_count(), local_zone());
671 Variable* arguments = info()->scope()->arguments();
672 if (arguments != nullptr && arguments->IsStackAllocated()) {
673 replacer.MarkPermanentlyLive(arguments->index());
674 }
675 liveness_analyzer()->Run(&replacer);
676 if (FLAG_trace_environment_liveness) {
677 OFStream os(stdout);
678 liveness_analyzer()->Print(os);
679 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680}
681
682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683// Gets the bailout id just before reading a variable proxy, but only for
684// unallocated variables.
685static BailoutId BeforeId(VariableProxy* proxy) {
686 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
687 : BailoutId::None();
688}
689
690
691static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
692#if DEBUG
693 const AstRawString* name = scope->parameter(index)->raw_name();
694 if (name && name->length() > 0) {
695 char* data = zone->NewArray<char>(name->length() + 1);
696 data[name->length()] = 0;
697 memcpy(data, name->raw_data(), name->length());
698 return data;
699 }
700#endif
701 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702}
703
704
705AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
706 Scope* scope,
707 Node* control_dependency)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 : builder_(builder),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709 parameters_count_(scope->num_parameters() + 1),
710 locals_count_(scope->num_stack_slots()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 liveness_block_(IsLivenessAnalysisEnabled()
712 ? builder_->liveness_analyzer()->NewBlock()
713 : nullptr),
714 values_(builder_->local_zone()),
715 contexts_(builder_->local_zone()),
716 control_dependency_(control_dependency),
717 effect_dependency_(control_dependency),
718 parameters_node_(nullptr),
719 locals_node_(nullptr),
720 stack_node_(nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
722
723 // Bind the receiver variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 int param_num = 0;
725 if (builder->info()->is_this_defined()) {
726 const Operator* op = common()->Parameter(param_num++, "%this");
727 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
728 values()->push_back(receiver);
729 } else {
730 values()->push_back(builder->jsgraph()->UndefinedConstant());
731 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000732
733 // Bind all parameter variables. The parameter indices are shifted by 1
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 // (receiver is variable index -1 but {Parameter} node index 0 and located at
735 // index 0 in the environment).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 for (int i = 0; i < scope->num_parameters(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
738 const Operator* op = common()->Parameter(param_num++, debug_name);
739 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740 values()->push_back(parameter);
741 }
742
743 // Bind all local variables to undefined.
744 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
745 values()->insert(values()->end(), locals_count(), undefined_constant);
746}
747
748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
750 LivenessAnalyzerBlock* liveness_block)
751 : builder_(copy->builder_),
752 parameters_count_(copy->parameters_count_),
753 locals_count_(copy->locals_count_),
754 liveness_block_(liveness_block),
755 values_(copy->zone()),
756 contexts_(copy->zone()),
757 control_dependency_(copy->control_dependency_),
758 effect_dependency_(copy->effect_dependency_),
759 parameters_node_(copy->parameters_node_),
760 locals_node_(copy->locals_node_),
761 stack_node_(copy->stack_node_) {
762 const size_t kStackEstimate = 7; // optimum from experimentation!
763 values_.reserve(copy->values_.size() + kStackEstimate);
764 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
765 contexts_.reserve(copy->contexts_.size());
766 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
767 copy->contexts_.end());
768}
769
770
771void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
772 DCHECK(variable->IsStackAllocated());
773 if (variable->IsParameter()) {
774 // The parameter indices are shifted by 1 (receiver is variable
775 // index -1 but located at index 0 in the environment).
776 values()->at(variable->index() + 1) = node;
777 } else {
778 DCHECK(variable->IsStackLocal());
779 values()->at(variable->index() + parameters_count_) = node;
780 DCHECK(IsLivenessBlockConsistent());
781 if (liveness_block() != nullptr) {
782 liveness_block()->Bind(variable->index());
783 }
784 }
785}
786
787
788Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
789 DCHECK(variable->IsStackAllocated());
790 if (variable->IsParameter()) {
791 // The parameter indices are shifted by 1 (receiver is variable
792 // index -1 but located at index 0 in the environment).
793 return values()->at(variable->index() + 1);
794 } else {
795 DCHECK(variable->IsStackLocal());
796 DCHECK(IsLivenessBlockConsistent());
797 if (liveness_block() != nullptr) {
798 liveness_block()->Lookup(variable->index());
799 }
800 return values()->at(variable->index() + parameters_count_);
801 }
802}
803
804
805void AstGraphBuilder::Environment::MarkAllLocalsLive() {
806 DCHECK(IsLivenessBlockConsistent());
807 if (liveness_block() != nullptr) {
808 for (int i = 0; i < locals_count_; i++) {
809 liveness_block()->Lookup(i);
810 }
811 }
812}
813
814
815void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
816 DCHECK_LT(index, parameters_count());
817 values()->at(index) = node;
818}
819
820
821Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
822 DCHECK_LT(index, parameters_count());
823 return values()->at(index);
824}
825
826
827AstGraphBuilder::Environment*
828AstGraphBuilder::Environment::CopyForConditional() {
829 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
830 if (liveness_block() != nullptr) {
831 copy_liveness_block =
832 builder_->liveness_analyzer()->NewBlock(liveness_block());
833 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
834 }
835 return new (zone()) Environment(this, copy_liveness_block);
836}
837
838
839AstGraphBuilder::Environment*
840AstGraphBuilder::Environment::CopyAsUnreachable() {
841 Environment* env = new (zone()) Environment(this, nullptr);
842 env->MarkAsUnreachable();
843 return env;
844}
845
846
847AstGraphBuilder::Environment*
848AstGraphBuilder::Environment::CopyAndShareLiveness() {
849 if (liveness_block() != nullptr) {
850 // Finish the current liveness block before copying.
851 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
852 }
853 Environment* env = new (zone()) Environment(this, liveness_block());
854 return env;
855}
856
857
858AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
859 BitVector* assigned, bool is_osr) {
860 PrepareForLoop(assigned, is_osr);
861 return CopyAndShareLiveness();
862}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863
864
865void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
866 int offset, int count) {
867 bool should_update = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
869 if (*state_values == nullptr || (*state_values)->InputCount() != count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 should_update = true;
871 } else {
872 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
873 for (int i = 0; i < count; i++) {
874 if ((*state_values)->InputAt(i) != env_values[i]) {
875 should_update = true;
876 break;
877 }
878 }
879 }
880 if (should_update) {
881 const Operator* op = common()->StateValues(count);
882 (*state_values) = graph()->NewNode(op, count, env_values);
883 }
884}
885
886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000887void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
888 Node** state_values, int offset, int count) {
889 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
890 *state_values = builder_->state_values_cache_.GetNodeForValues(
891 env_values, static_cast<size_t>(count));
892}
893
Ben Murdoch097c5b22016-05-18 11:27:45 +0100894Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
895 OutputFrameStateCombine combine,
896 bool owner_has_exception) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000897 if (!builder()->info()->is_deoptimization_enabled()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100898 return builder()->GetEmptyFrameState();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 }
900
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 UpdateStateValues(&parameters_node_, 0, parameters_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
904 stack_height());
905
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 const Operator* op = common()->FrameState(
907 ast_id, combine, builder()->frame_state_function_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
910 stack_node_, builder()->current_context(),
911 builder()->GetFunctionClosure(),
912 builder()->graph()->start());
913
914 DCHECK(IsLivenessBlockConsistent());
915 if (liveness_block() != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100916 // If the owning node has an exception, register the checkpoint to the
917 // predecessor so that the checkpoint is used for both the normal and the
918 // exceptional paths. Yes, this is a terrible hack and we might want
919 // to use an explicit frame state for the exceptional path.
920 if (owner_has_exception) {
921 liveness_block()->GetPredecessor()->Checkpoint(result);
922 } else {
923 liveness_block()->Checkpoint(result);
924 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 }
926 return result;
927}
928
929
930bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
931 return FLAG_analyze_environment_liveness &&
932 builder()->info()->is_deoptimization_enabled();
933}
934
935
936bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
937 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
938 (liveness_block() == nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939}
940
941
942AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
943 Expression::Context kind)
944 : kind_(kind), owner_(own), outer_(own->ast_context()) {
945 owner()->set_ast_context(this); // Push.
946#ifdef DEBUG
947 original_height_ = environment()->stack_height();
948#endif
949}
950
951
952AstGraphBuilder::AstContext::~AstContext() {
953 owner()->set_ast_context(outer_); // Pop.
954}
955
956
957AstGraphBuilder::AstEffectContext::~AstEffectContext() {
958 DCHECK(environment()->stack_height() == original_height_);
959}
960
961
962AstGraphBuilder::AstValueContext::~AstValueContext() {
963 DCHECK(environment()->stack_height() == original_height_ + 1);
964}
965
966
967AstGraphBuilder::AstTestContext::~AstTestContext() {
968 DCHECK(environment()->stack_height() == original_height_ + 1);
969}
970
971
972void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
973 // The value is ignored.
974}
975
976
977void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
978 environment()->Push(value);
979}
980
981
982void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984}
985
986
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988
989
990Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
991 return environment()->Pop();
992}
993
994
995Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
996 return environment()->Pop();
997}
998
999
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000Scope* AstGraphBuilder::current_scope() const {
1001 return execution_context_->scope();
1002}
1003
1004
1005Node* AstGraphBuilder::current_context() const {
1006 return environment()->Context();
1007}
1008
1009
1010void AstGraphBuilder::ControlScope::PerformCommand(Command command,
1011 Statement* target,
1012 Node* value) {
1013 Environment* env = environment()->CopyAsUnreachable();
1014 ControlScope* current = this;
1015 while (current != nullptr) {
1016 environment()->TrimStack(current->stack_height());
1017 environment()->TrimContextChain(current->context_length());
1018 if (current->Execute(command, target, value)) break;
1019 current = current->outer_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 builder()->set_environment(env);
1022 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023}
1024
1025
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
1027 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028}
1029
1030
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001031void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
1032 PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
1033}
1034
1035
1036void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
1037 PerformCommand(CMD_RETURN, nullptr, return_value);
1038}
1039
1040
1041void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
1042 PerformCommand(CMD_THROW, nullptr, exception_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043}
1044
1045
1046void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 if (expr == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 return environment()->Push(jsgraph()->NullConstant());
1049 }
1050 VisitForValue(expr);
1051}
1052
1053
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1055 if (expr == nullptr) {
1056 return environment()->Push(jsgraph()->TheHoleConstant());
1057 }
1058 VisitForValue(expr);
1059}
1060
1061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1063 for (int i = 0; i < exprs->length(); ++i) {
1064 VisitForValue(exprs->at(i));
1065 }
1066}
1067
1068
1069void AstGraphBuilder::VisitForValue(Expression* expr) {
1070 AstValueContext for_value(this);
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());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075 }
1076}
1077
1078
1079void AstGraphBuilder::VisitForEffect(Expression* expr) {
1080 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 } else {
1084 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 }
1086}
1087
1088
1089void AstGraphBuilder::VisitForTest(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 AstTestContext for_condition(this, expr->test_id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001091 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001093 } else {
1094 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1095 }
1096}
1097
1098
1099void AstGraphBuilder::Visit(Expression* expr) {
1100 // Reuses enclosing AstContext.
1101 if (!CheckStackOverflow()) {
1102 expr->Accept(this);
1103 } else {
1104 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 }
1106}
1107
1108
1109void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1110 Variable* variable = decl->proxy()->var();
1111 VariableMode mode = decl->mode();
Ben Murdochc5610432016-08-08 18:44:38 +01001112 bool hole_init = mode == CONST || mode == LET;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001113 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114 case VariableLocation::GLOBAL:
Ben Murdochc5610432016-08-08 18:44:38 +01001115 case VariableLocation::UNALLOCATED:
1116 DCHECK(!variable->binding_needs_init());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001117 globals()->push_back(variable->name());
Ben Murdochc5610432016-08-08 18:44:38 +01001118 globals()->push_back(isolate()->factory()->undefined_value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 case VariableLocation::PARAMETER:
1121 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 if (hole_init) {
1123 Node* value = jsgraph()->TheHoleConstant();
1124 environment()->Bind(variable, value);
1125 }
1126 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 case VariableLocation::CONTEXT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 if (hole_init) {
1129 Node* value = jsgraph()->TheHoleConstant();
1130 const Operator* op = javascript()->StoreContext(0, variable->index());
1131 NewNode(op, current_context(), value);
1132 }
1133 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001134 case VariableLocation::LOOKUP: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001135 DCHECK(!hole_init);
Ben Murdochc5610432016-08-08 18:44:38 +01001136 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001137 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareEvalVar);
1138 Node* store = NewNode(op, name);
Ben Murdochc5610432016-08-08 18:44:38 +01001139 PrepareFrameState(store, decl->proxy()->id());
1140 break;
1141 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001142 }
1143}
1144
1145
1146void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1147 Variable* variable = decl->proxy()->var();
1148 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 case VariableLocation::GLOBAL:
1150 case VariableLocation::UNALLOCATED: {
1151 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1152 decl->fun(), info()->script(), info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 // Check for stack-overflow exception.
1154 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001155 globals()->push_back(variable->name());
1156 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 break;
1158 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159 case VariableLocation::PARAMETER:
1160 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 VisitForValue(decl->fun());
1162 Node* value = environment()->Pop();
1163 environment()->Bind(variable, value);
1164 break;
1165 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167 VisitForValue(decl->fun());
1168 Node* value = environment()->Pop();
1169 const Operator* op = javascript()->StoreContext(0, variable->index());
1170 NewNode(op, current_context(), value);
1171 break;
1172 }
Ben Murdochc5610432016-08-08 18:44:38 +01001173 case VariableLocation::LOOKUP: {
1174 VisitForValue(decl->fun());
1175 Node* value = environment()->Pop();
1176 Node* name = jsgraph()->Constant(variable->name());
Ben Murdochc5610432016-08-08 18:44:38 +01001177 const Operator* op =
Ben Murdoch61f157c2016-09-16 13:49:30 +01001178 javascript()->CallRuntime(Runtime::kDeclareEvalFunction);
1179 Node* store = NewNode(op, name, value);
Ben Murdochc5610432016-08-08 18:44:38 +01001180 PrepareFrameState(store, decl->proxy()->id());
1181 break;
1182 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001183 }
1184}
1185
1186
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1188 UNREACHABLE();
1189}
1190
1191
1192void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1193 UNREACHABLE();
1194}
1195
1196
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197void AstGraphBuilder::VisitBlock(Block* stmt) {
1198 BlockBuilder block(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 ControlScopeForBreakable scope(this, stmt, &block);
1200 if (stmt->labels() != nullptr) block.BeginBlock();
1201 if (stmt->scope() == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 // Visit statements in the same scope, no declarations.
1203 VisitStatements(stmt->statements());
1204 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205 // Visit declarations and statements in a block scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 if (stmt->scope()->NeedsContext()) {
1207 Node* context = BuildLocalBlockContext(stmt->scope());
1208 ContextScope scope(this, stmt->scope(), context);
1209 VisitDeclarations(stmt->scope()->declarations());
1210 VisitStatements(stmt->statements());
1211 } else {
1212 VisitDeclarations(stmt->scope()->declarations());
1213 VisitStatements(stmt->statements());
1214 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001215 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 if (stmt->labels() != nullptr) block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001217}
1218
1219
1220void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1221 VisitForEffect(stmt->expression());
1222}
1223
1224
1225void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1226 // Do nothing.
1227}
1228
1229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1231 SloppyBlockFunctionStatement* stmt) {
1232 Visit(stmt->statement());
1233}
1234
1235
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1237 IfBuilder compare_if(this);
1238 VisitForTest(stmt->condition());
1239 Node* condition = environment()->Pop();
1240 compare_if.If(condition);
1241 compare_if.Then();
1242 Visit(stmt->then_statement());
1243 compare_if.Else();
1244 Visit(stmt->else_statement());
1245 compare_if.End();
1246}
1247
1248
1249void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 execution_control()->ContinueTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251}
1252
1253
1254void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 execution_control()->BreakTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256}
1257
1258
1259void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1260 VisitForValue(stmt->expression());
1261 Node* result = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262 execution_control()->ReturnValue(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263}
1264
1265
1266void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1267 VisitForValue(stmt->expression());
1268 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 Node* object = BuildToObject(value, stmt->ToObjectId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 const Operator* op = javascript()->CreateWithContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 Node* context = NewNode(op, object, GetFunctionClosureForContext());
1272 PrepareFrameState(context, stmt->EntryId());
1273 VisitInScope(stmt->statement(), stmt->scope(), context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274}
1275
1276
1277void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1278 ZoneList<CaseClause*>* clauses = stmt->cases();
1279 SwitchBuilder compare_switch(this, clauses->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 ControlScopeForBreakable scope(this, stmt, &compare_switch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 compare_switch.BeginSwitch();
1282 int default_index = -1;
1283
1284 // Keep the switch value on the stack until a case matches.
1285 VisitForValue(stmt->tag());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001286
1287 // Iterate over all cases and create nodes for label comparison.
1288 for (int i = 0; i < clauses->length(); i++) {
1289 CaseClause* clause = clauses->at(i);
1290
1291 // The default is not a test, remember index.
1292 if (clause->is_default()) {
1293 default_index = i;
1294 continue;
1295 }
1296
1297 // Create nodes to perform label comparison as if via '==='. The switch
1298 // value is still on the operand stack while the label is evaluated.
1299 VisitForValue(clause->label());
1300 Node* label = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001301 Node* tag = environment()->Top();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001302
1303 CompareOperationHints hints;
1304 if (!type_hint_analysis_ ||
1305 !type_hint_analysis_->GetCompareOperationHints(clause->CompareId(),
1306 &hints)) {
1307 hints = CompareOperationHints::Any();
1308 }
1309
1310 const Operator* op = javascript()->StrictEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 Node* condition = NewNode(op, tag, label);
1312 compare_switch.BeginLabel(i, condition);
1313
1314 // Discard the switch value at label match.
1315 environment()->Pop();
1316 compare_switch.EndLabel();
1317 }
1318
1319 // Discard the switch value and mark the default case.
1320 environment()->Pop();
1321 if (default_index >= 0) {
1322 compare_switch.DefaultAt(default_index);
1323 }
1324
1325 // Iterate over all cases and create nodes for case bodies.
1326 for (int i = 0; i < clauses->length(); i++) {
1327 CaseClause* clause = clauses->at(i);
1328 compare_switch.BeginCase(i);
1329 VisitStatements(clause->statements());
1330 compare_switch.EndCase();
1331 }
1332
1333 compare_switch.EndSwitch();
1334}
1335
1336
1337void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1338 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1340 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 while_loop.EndBody();
1342 VisitForTest(stmt->cond());
1343 Node* condition = environment()->Pop();
1344 while_loop.BreakUnless(condition);
1345 while_loop.EndLoop();
1346}
1347
1348
1349void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1350 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 VisitForTest(stmt->cond());
1353 Node* condition = environment()->Pop();
1354 while_loop.BreakUnless(condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 while_loop.EndBody();
1357 while_loop.EndLoop();
1358}
1359
1360
1361void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1362 LoopBuilder for_loop(this);
1363 VisitIfNotNull(stmt->init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1365 if (stmt->cond() != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 VisitForTest(stmt->cond());
1367 Node* condition = environment()->Pop();
1368 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001369 } else {
1370 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 for_loop.EndBody();
1374 VisitIfNotNull(stmt->next());
1375 for_loop.EndLoop();
1376}
1377
1378
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1380 VisitForValue(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 Node* object = environment()->Pop();
1382 BlockBuilder for_block(this);
1383 for_block.BeginBlock();
1384 // Check for null or undefined before entering loop.
1385 Node* is_null_cond =
Ben Murdoch61f157c2016-09-16 13:49:30 +01001386 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
1387 jsgraph()->NullConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001389 Node* is_undefined_cond =
1390 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
1391 jsgraph()->UndefinedConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001393 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001394 // Convert object to jsobject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395 object = BuildToObject(object, stmt->ToObjectId());
1396 environment()->Push(object);
1397
1398 // Prepare for-in cache.
1399 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001400 PrepareFrameState(prepare, stmt->PrepareId(),
1401 OutputFrameStateCombine::Push(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402 Node* cache_type = NewNode(common()->Projection(0), prepare);
1403 Node* cache_array = NewNode(common()->Projection(1), prepare);
1404 Node* cache_length = NewNode(common()->Projection(2), prepare);
1405
1406 // Construct the rest of the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 environment()->Push(cache_type);
1408 environment()->Push(cache_array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 environment()->Push(cache_length);
1410 environment()->Push(jsgraph()->ZeroConstant());
1411
1412 // Build the actual loop body.
1413 LoopBuilder for_loop(this);
1414 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001415 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 // These stack values are renamed in the case of OSR, so reload them
1417 // from the environment.
1418 Node* index = environment()->Peek(0);
1419 Node* cache_length = environment()->Peek(1);
1420 Node* cache_array = environment()->Peek(2);
1421 Node* cache_type = environment()->Peek(3);
1422 Node* object = environment()->Peek(4);
1423
1424 // Check loop termination condition.
1425 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1426 for_loop.BreakWhen(exit_cond);
1427
1428 // Compute the next enumerated value.
1429 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1430 cache_type, index);
1431 PrepareFrameState(value, stmt->FilterId(),
1432 OutputFrameStateCombine::Push());
1433 IfBuilder test_value(this);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001434 Node* test_value_cond =
1435 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
1436 value, jsgraph()->UndefinedConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001437 test_value.If(test_value_cond, BranchHint::kFalse);
1438 test_value.Then();
1439 test_value.Else();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001441 // Bind value and do loop body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001442 VectorSlotPair feedback =
1443 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1444 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1445 stmt->AssignmentId());
1446 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001447 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001448 test_value.End();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001449 for_loop.EndBody();
1450
1451 // Increment counter and continue.
Ben Murdochc5610432016-08-08 18:44:38 +01001452 index = environment()->Peek(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001453 index = NewNode(javascript()->ForInStep(), index);
1454 environment()->Poke(0, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 for_loop.EndLoop();
1457 environment()->Drop(5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001459 for_block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460}
1461
1462
1463void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001464 LoopBuilder for_loop(this);
1465 VisitForEffect(stmt->assign_iterator());
1466 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1467 VisitForEffect(stmt->next_result());
1468 VisitForTest(stmt->result_done());
1469 Node* condition = environment()->Pop();
1470 for_loop.BreakWhen(condition);
1471 VisitForEffect(stmt->assign_each());
1472 VisitIterationBody(stmt, &for_loop);
1473 for_loop.EndBody();
1474 for_loop.EndLoop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001475}
1476
1477
1478void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001479 TryCatchBuilder try_control(this);
1480
1481 // Evaluate the try-block inside a control scope. This simulates a handler
1482 // that is intercepting 'throw' control commands.
1483 try_control.BeginTry();
1484 {
1485 ControlScopeForCatch scope(this, &try_control);
1486 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1487 environment()->Push(current_context());
1488 Visit(stmt->try_block());
1489 environment()->Pop();
1490 }
1491 try_control.EndTry();
1492
Ben Murdochda12d292016-06-02 14:46:10 +01001493 // If requested, clear message object as we enter the catch block.
1494 if (stmt->clear_pending_message()) {
1495 Node* the_hole = jsgraph()->TheHoleConstant();
1496 NewNode(javascript()->StoreMessage(), the_hole);
1497 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498
1499 // Create a catch scope that binds the exception.
1500 Node* exception = try_control.GetExceptionNode();
1501 Handle<String> name = stmt->variable()->name();
1502 const Operator* op = javascript()->CreateCatchContext(name);
1503 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1504
1505 // Evaluate the catch-block.
1506 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1507 try_control.EndCatch();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508}
1509
1510
1511void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 TryFinallyBuilder try_control(this);
1513
1514 // We keep a record of all paths that enter the finally-block to be able to
1515 // dispatch to the correct continuation point after the statements in the
1516 // finally-block have been evaluated.
1517 //
1518 // The try-finally construct can enter the finally-block in three ways:
1519 // 1. By exiting the try-block normally, falling through at the end.
1520 // 2. By exiting the try-block with a function-local control flow transfer
1521 // (i.e. through break/continue/return statements).
1522 // 3. By exiting the try-block with a thrown exception.
1523 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1524 ControlScope::DeferredCommands* commands =
1525 new (local_zone()) ControlScope::DeferredCommands(this);
1526
1527 // Evaluate the try-block inside a control scope. This simulates a handler
1528 // that is intercepting all control commands.
1529 try_control.BeginTry();
1530 {
1531 ControlScopeForFinally scope(this, commands, &try_control);
1532 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1533 environment()->Push(current_context());
1534 Visit(stmt->try_block());
1535 environment()->Pop();
1536 }
1537 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539 // The result value semantics depend on how the block was entered:
1540 // - ReturnStatement: It represents the return value being returned.
1541 // - ThrowStatement: It represents the exception being thrown.
1542 // - BreakStatement/ContinueStatement: Filled with the hole.
1543 // - Falling through into finally-block: Filled with the hole.
1544 Node* result = try_control.GetResultValueNode();
1545 Node* token = try_control.GetDispatchTokenNode();
1546
1547 // The result value, dispatch token and message is expected on the operand
1548 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1549 Node* message = NewNode(javascript()->LoadMessage());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001550 environment()->Push(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 environment()->Push(result);
1552 environment()->Push(message);
1553
1554 // Clear message object as we enter the finally block.
1555 Node* the_hole = jsgraph()->TheHoleConstant();
1556 NewNode(javascript()->StoreMessage(), the_hole);
1557
1558 // Evaluate the finally-block.
1559 Visit(stmt->finally_block());
1560 try_control.EndFinally();
1561
1562 // The result value, dispatch token and message is restored from the operand
1563 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1564 message = environment()->Pop();
1565 result = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001566 token = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 NewNode(javascript()->StoreMessage(), message);
1568
1569 // Dynamic dispatch after the finally-block.
1570 commands->ApplyDeferredCommands(token, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571}
1572
1573
1574void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 Node* node =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001576 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001577 PrepareFrameState(node, stmt->DebugBreakId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001578 environment()->MarkAllLocalsLive();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579}
1580
1581
1582void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 // Find or build a shared function info.
1584 Handle<SharedFunctionInfo> shared_info =
1585 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1586 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001587
1588 // Create node to instantiate a new closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001589 PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1590 const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1591 Node* value = NewNode(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592 ast_context()->ProduceValue(value);
1593}
1594
1595
1596void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001597 // Visit declarations and class literal in a block scope.
1598 if (expr->scope()->ContextLocalCount() > 0) {
1599 Node* context = BuildLocalBlockContext(expr->scope());
1600 ContextScope scope(this, expr->scope(), context);
1601 VisitDeclarations(expr->scope()->declarations());
1602 VisitClassLiteralContents(expr);
1603 } else {
1604 VisitDeclarations(expr->scope()->declarations());
1605 VisitClassLiteralContents(expr);
1606 }
1607}
1608
1609
1610void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 VisitForValueOrTheHole(expr->extends());
1612 VisitForValue(expr->constructor());
1613
1614 // Create node to instantiate a new class.
1615 Node* constructor = environment()->Pop();
1616 Node* extends = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 Node* start = jsgraph()->Constant(expr->start_position());
1618 Node* end = jsgraph()->Constant(expr->end_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001619 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
1620 Node* literal = NewNode(opc, extends, constructor, start, end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 PrepareFrameState(literal, expr->CreateLiteralId(),
1622 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623 environment()->Push(literal);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001624
1625 // Load the "prototype" from the constructor.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001626 PrepareEagerCheckpoint(expr->CreateLiteralId());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001627 Handle<Name> name = isolate()->factory()->prototype_string();
1628 VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
1629 Node* prototype = BuildNamedLoad(literal, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001630 PrepareFrameState(prototype, expr->PrototypeId(),
1631 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 environment()->Push(prototype);
1633
1634 // Create nodes to store method values into the literal.
1635 for (int i = 0; i < expr->properties()->length(); i++) {
1636 ObjectLiteral::Property* property = expr->properties()->at(i);
1637 environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1638
1639 VisitForValue(property->key());
1640 Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1641 environment()->Push(name);
1642
1643 // The static prototype property is read only. We handle the non computed
1644 // property name case in the parser. Since this is the only case where we
1645 // need to check for an own read only property we special case this so we do
1646 // not need to do this for every property.
1647 if (property->is_static() && property->is_computed_name()) {
1648 Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1649 expr->GetIdForProperty(i));
1650 environment()->Push(check);
1651 }
1652
1653 VisitForValue(property->value());
1654 Node* value = environment()->Pop();
1655 Node* key = environment()->Pop();
1656 Node* receiver = environment()->Pop();
1657
1658 BuildSetHomeObject(value, receiver, property);
1659
1660 switch (property->kind()) {
1661 case ObjectLiteral::Property::CONSTANT:
1662 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1663 case ObjectLiteral::Property::PROTOTYPE:
1664 UNREACHABLE();
1665 case ObjectLiteral::Property::COMPUTED: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001666 Node* attr = jsgraph()->Constant(DONT_ENUM);
1667 Node* set_function_name =
1668 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001670 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001671 Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
1672 PrepareFrameState(call, BailoutId::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001673 break;
1674 }
1675 case ObjectLiteral::Property::GETTER: {
1676 Node* attr = jsgraph()->Constant(DONT_ENUM);
1677 const Operator* op = javascript()->CallRuntime(
1678 Runtime::kDefineGetterPropertyUnchecked, 4);
1679 NewNode(op, receiver, key, value, attr);
1680 break;
1681 }
1682 case ObjectLiteral::Property::SETTER: {
1683 Node* attr = jsgraph()->Constant(DONT_ENUM);
1684 const Operator* op = javascript()->CallRuntime(
1685 Runtime::kDefineSetterPropertyUnchecked, 4);
1686 NewNode(op, receiver, key, value, attr);
1687 break;
1688 }
1689 }
1690 }
1691
Ben Murdochc5610432016-08-08 18:44:38 +01001692 // Set the constructor to have fast properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001693 prototype = environment()->Pop();
1694 literal = environment()->Pop();
Ben Murdochc5610432016-08-08 18:44:38 +01001695 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
1696 literal = NewNode(op, literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001697
1698 // Assign to class variable.
1699 if (expr->class_variable_proxy() != nullptr) {
1700 Variable* var = expr->class_variable_proxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001701 VectorSlotPair feedback = CreateVectorSlotPair(
1702 expr->NeedsProxySlot() ? expr->ProxySlot()
1703 : FeedbackVectorSlot::Invalid());
1704 BuildVariableAssignment(var, literal, Token::INIT, feedback,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001705 BailoutId::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706 }
1707 ast_context()->ProduceValue(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708}
1709
1710
1711void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1712 UNREACHABLE();
1713}
1714
1715
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001716void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1717 VisitBlock(expr->block());
1718 VisitVariableProxy(expr->result());
1719 ast_context()->ReplaceValue();
1720}
1721
1722
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001723void AstGraphBuilder::VisitConditional(Conditional* expr) {
1724 IfBuilder compare_if(this);
1725 VisitForTest(expr->condition());
1726 Node* condition = environment()->Pop();
1727 compare_if.If(condition);
1728 compare_if.Then();
1729 Visit(expr->then_expression());
1730 compare_if.Else();
1731 Visit(expr->else_expression());
1732 compare_if.End();
1733 ast_context()->ReplaceValue();
1734}
1735
1736
1737void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001738 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001739 PrepareEagerCheckpoint(BeforeId(expr));
1740 Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001741 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 ast_context()->ProduceValue(value);
1743}
1744
1745
1746void AstGraphBuilder::VisitLiteral(Literal* expr) {
1747 Node* value = jsgraph()->Constant(expr->value());
1748 ast_context()->ProduceValue(value);
1749}
1750
1751
1752void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1753 Node* closure = GetFunctionClosure();
1754
1755 // Create node to materialize a regular expression literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 const Operator* op = javascript()->CreateLiteralRegExp(
1757 expr->pattern(), expr->flags(), expr->literal_index());
1758 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001759 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001760 ast_context()->ProduceValue(literal);
1761}
1762
1763
1764void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1765 Node* closure = GetFunctionClosure();
1766
1767 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 const Operator* op = javascript()->CreateLiteralObject(
1769 expr->constant_properties(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001770 expr->literal_index(), expr->properties_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001771 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001772 PrepareFrameState(literal, expr->CreateLiteralId(),
1773 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774
1775 // The object is expected on the operand stack during computation of the
1776 // property values and is the value of the entire expression.
1777 environment()->Push(literal);
1778
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001779 // Create nodes to store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001780 int property_index = 0;
1781 AccessorTable accessor_table(local_zone());
1782 for (; property_index < expr->properties()->length(); property_index++) {
1783 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1784 if (property->is_computed_name()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785 if (property->IsCompileTimeValue()) continue;
1786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001787 Literal* key = property->key()->AsLiteral();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001788 switch (property->kind()) {
1789 case ObjectLiteral::Property::CONSTANT:
1790 UNREACHABLE();
1791 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1792 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1793 // Fall through.
1794 case ObjectLiteral::Property::COMPUTED: {
1795 // It is safe to use [[Put]] here because the boilerplate already
1796 // contains computed properties with an uninitialized value.
1797 if (key->value()->IsInternalizedString()) {
1798 if (property->emit_store()) {
1799 VisitForValue(property->value());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001800 PrepareEagerCheckpoint(property->value()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001801 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001802 Node* literal = environment()->Top();
1803 Handle<Name> name = key->AsPropertyName();
1804 VectorSlotPair feedback =
1805 CreateVectorSlotPair(property->GetSlot(0));
1806 Node* store = BuildNamedStore(literal, name, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001807 PrepareFrameState(store, key->id(),
1808 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001809 BuildSetHomeObject(value, literal, property, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001810 } else {
1811 VisitForEffect(property->value());
1812 }
1813 break;
1814 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001816 VisitForValue(property->key());
1817 VisitForValue(property->value());
1818 Node* value = environment()->Pop();
1819 Node* key = environment()->Pop();
1820 Node* receiver = environment()->Pop();
1821 if (property->emit_store()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 Node* language = jsgraph()->Constant(SLOPPY);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001823 const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001824 Node* set_property = NewNode(op, receiver, key, value, language);
1825 // SetProperty should not lazy deopt on an object literal.
1826 PrepareFrameState(set_property, BailoutId::None());
1827 BuildSetHomeObject(value, receiver, property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 }
1829 break;
1830 }
1831 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001832 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 VisitForValue(property->value());
1834 Node* value = environment()->Pop();
1835 Node* receiver = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001836 DCHECK(property->emit_store());
1837 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001838 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 Node* set_prototype = NewNode(op, receiver, value);
1840 // SetPrototype should not lazy deopt on an object literal.
1841 PrepareFrameState(set_prototype,
1842 expr->GetIdForPropertySet(property_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843 break;
1844 }
1845 case ObjectLiteral::Property::GETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001846 if (property->emit_store()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001847 AccessorTable::Iterator it = accessor_table.lookup(key);
1848 it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1849 it->second->getter = property;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001850 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001851 break;
1852 case ObjectLiteral::Property::SETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001853 if (property->emit_store()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001854 AccessorTable::Iterator it = accessor_table.lookup(key);
1855 it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1856 it->second->setter = property;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001857 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001858 break;
1859 }
1860 }
1861
1862 // Create nodes to define accessors, using only a single call to the runtime
1863 // for each pair of corresponding getters and setters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001864 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 for (AccessorTable::Iterator it = accessor_table.begin();
1866 it != accessor_table.end(); ++it) {
1867 VisitForValue(it->first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001868 VisitObjectLiteralAccessor(literal, it->second->getter);
1869 VisitObjectLiteralAccessor(literal, it->second->setter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001870 Node* setter = environment()->Pop();
1871 Node* getter = environment()->Pop();
1872 Node* name = environment()->Pop();
1873 Node* attr = jsgraph()->Constant(NONE);
1874 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001875 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 Node* call = NewNode(op, literal, name, getter, setter, attr);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001877 PrepareFrameState(call, it->second->bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001878 }
1879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001880 // Object literals have two parts. The "static" part on the left contains no
1881 // computed property names, and so we can compute its map ahead of time; see
1882 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1883 // with the first computed property name and continues with all properties to
1884 // its right. All the code from above initializes the static component of the
1885 // object literal, and arranges for the map of the result to reflect the
1886 // static order in which the keys appear. For the dynamic properties, we
1887 // compile them into a series of "SetOwnProperty" runtime calls. This will
1888 // preserve insertion order.
1889 for (; property_index < expr->properties()->length(); property_index++) {
1890 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1891
1892 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1893 environment()->Push(environment()->Top()); // Duplicate receiver.
1894 VisitForValue(property->value());
1895 Node* value = environment()->Pop();
1896 Node* receiver = environment()->Pop();
1897 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001898 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899 Node* call = NewNode(op, receiver, value);
1900 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1901 continue;
1902 }
1903
1904 environment()->Push(environment()->Top()); // Duplicate receiver.
1905 VisitForValue(property->key());
1906 Node* name = BuildToName(environment()->Pop(),
1907 expr->GetIdForPropertyName(property_index));
1908 environment()->Push(name);
1909 VisitForValue(property->value());
1910 Node* value = environment()->Pop();
1911 Node* key = environment()->Pop();
1912 Node* receiver = environment()->Pop();
1913 BuildSetHomeObject(value, receiver, property);
1914 switch (property->kind()) {
1915 case ObjectLiteral::Property::CONSTANT:
1916 case ObjectLiteral::Property::COMPUTED:
1917 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1918 Node* attr = jsgraph()->Constant(NONE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001919 Node* set_function_name =
1920 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001921 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001922 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001923 Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
1924 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001925 break;
1926 }
1927 case ObjectLiteral::Property::PROTOTYPE:
1928 UNREACHABLE(); // Handled specially above.
1929 break;
1930 case ObjectLiteral::Property::GETTER: {
1931 Node* attr = jsgraph()->Constant(NONE);
1932 const Operator* op = javascript()->CallRuntime(
1933 Runtime::kDefineGetterPropertyUnchecked, 4);
1934 Node* call = NewNode(op, receiver, key, value, attr);
1935 PrepareFrameState(call, BailoutId::None());
1936 break;
1937 }
1938 case ObjectLiteral::Property::SETTER: {
1939 Node* attr = jsgraph()->Constant(NONE);
1940 const Operator* op = javascript()->CallRuntime(
1941 Runtime::kDefineSetterPropertyUnchecked, 4);
1942 Node* call = NewNode(op, receiver, key, value, attr);
1943 PrepareFrameState(call, BailoutId::None());
1944 break;
1945 }
1946 }
1947 }
1948
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001949 ast_context()->ProduceValue(environment()->Pop());
1950}
1951
1952
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001953void AstGraphBuilder::VisitObjectLiteralAccessor(
1954 Node* home_object, ObjectLiteralProperty* property) {
1955 if (property == nullptr) {
1956 VisitForValueOrNull(nullptr);
1957 } else {
1958 VisitForValue(property->value());
1959 BuildSetHomeObject(environment()->Top(), home_object, property);
1960 }
1961}
1962
1963
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001964void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1965 Node* closure = GetFunctionClosure();
1966
1967 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001968 const Operator* op = javascript()->CreateLiteralArray(
1969 expr->constant_elements(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001970 expr->literal_index(), expr->values()->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001971 Node* literal = NewNode(op, closure);
1972 PrepareFrameState(literal, expr->CreateLiteralId(),
1973 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001975 // The array is expected on the operand stack during computation of the
1976 // element values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001977 environment()->Push(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001978
1979 // Create nodes to evaluate all the non-constant subexpressions and to store
1980 // them into the newly cloned array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001981 int array_index = 0;
1982 for (; array_index < expr->values()->length(); array_index++) {
1983 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001984 DCHECK(!subexpr->IsSpread());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001985 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1986
1987 VisitForValue(subexpr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001988 {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001989 PrepareEagerCheckpoint(subexpr->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001990 VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1991 Node* value = environment()->Pop();
1992 Node* index = jsgraph()->Constant(array_index);
1993 Node* literal = environment()->Top();
1994 Node* store = BuildKeyedStore(literal, index, value, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001995 PrepareFrameState(store, expr->GetIdForElement(array_index),
1996 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001997 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001998 }
1999
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002000 // In case the array literal contains spread expressions it has two parts. The
2001 // first part is the "static" array which has a literal index is handled
2002 // above. The second part is the part after the first spread expression
2003 // (inclusive) and these elements gets appended to the array. Note that the
2004 // number elements an iterable produces is unknown ahead of time.
2005 for (; array_index < expr->values()->length(); array_index++) {
2006 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002007 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002008
Ben Murdoch097c5b22016-05-18 11:27:45 +01002009 VisitForValue(subexpr);
2010 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002011 Node* value = environment()->Pop();
2012 Node* array = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002013 const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
2014 Node* result = NewNode(op, array, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002015 PrepareFrameState(result, expr->GetIdForElement(array_index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01002016 environment()->Push(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002017 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002018 }
2019
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002020 ast_context()->ProduceValue(environment()->Pop());
2021}
2022
2023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002024void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
2025 const VectorSlotPair& feedback,
2026 BailoutId bailout_id_before,
2027 BailoutId bailout_id_after) {
2028 DCHECK(expr->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002029
2030 // Left-hand side can only be a property, a global or a variable slot.
2031 Property* property = expr->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002032 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002033
2034 // Evaluate LHS expression and store the value.
2035 switch (assign_type) {
2036 case VARIABLE: {
2037 Variable* var = expr->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002038 environment()->Push(value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002039 PrepareEagerCheckpoint(bailout_id_before);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002040 value = environment()->Pop();
2041 BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
Ben Murdoch61f157c2016-09-16 13:49:30 +01002042 bailout_id_after);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002043 break;
2044 }
2045 case NAMED_PROPERTY: {
2046 environment()->Push(value);
2047 VisitForValue(property->obj());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002048 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002049 Node* object = environment()->Pop();
2050 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002051 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2052 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002053 PrepareFrameState(store, bailout_id_after,
2054 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002055 break;
2056 }
2057 case KEYED_PROPERTY: {
2058 environment()->Push(value);
2059 VisitForValue(property->obj());
2060 VisitForValue(property->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002061 PrepareEagerCheckpoint(property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062 Node* key = environment()->Pop();
2063 Node* object = environment()->Pop();
2064 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002065 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002066 PrepareFrameState(store, bailout_id_after,
2067 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002068 break;
2069 }
2070 case NAMED_SUPER_PROPERTY: {
2071 environment()->Push(value);
2072 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2073 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002074 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002075 Node* home_object = environment()->Pop();
2076 Node* receiver = environment()->Pop();
2077 value = environment()->Pop();
2078 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2079 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002080 PrepareFrameState(store, bailout_id_after,
2081 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002082 break;
2083 }
2084 case KEYED_SUPER_PROPERTY: {
2085 environment()->Push(value);
2086 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2087 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2088 VisitForValue(property->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002089 PrepareEagerCheckpoint(property->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002090 Node* key = environment()->Pop();
2091 Node* home_object = environment()->Pop();
2092 Node* receiver = environment()->Pop();
2093 value = environment()->Pop();
2094 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002095 PrepareFrameState(store, bailout_id_after,
2096 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002097 break;
2098 }
2099 }
2100}
2101
2102
2103void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002104 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002105
2106 // Left-hand side can only be a property, a global or a variable slot.
2107 Property* property = expr->target()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002108 LhsKind assign_type = Property::GetAssignType(property);
2109 bool needs_frame_state_before = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002110
2111 // Evaluate LHS expression.
2112 switch (assign_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002113 case VARIABLE: {
2114 Variable* variable = expr->target()->AsVariableProxy()->var();
2115 if (variable->location() == VariableLocation::PARAMETER ||
2116 variable->location() == VariableLocation::LOCAL ||
2117 variable->location() == VariableLocation::CONTEXT) {
2118 needs_frame_state_before = false;
2119 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002120 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002121 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002122 case NAMED_PROPERTY:
2123 VisitForValue(property->obj());
2124 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002125 case KEYED_PROPERTY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002126 VisitForValue(property->obj());
2127 VisitForValue(property->key());
2128 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002129 case NAMED_SUPER_PROPERTY:
2130 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2131 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2132 break;
2133 case KEYED_SUPER_PROPERTY:
2134 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2135 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2136 VisitForValue(property->key());
2137 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002138 }
2139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002140 BailoutId before_store_id = BailoutId::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002141 // Evaluate the value and potentially handle compound assignments by loading
2142 // the left-hand side value and performing a binary operation.
2143 if (expr->is_compound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002144 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002145 switch (assign_type) {
2146 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002147 VariableProxy* proxy = expr->target()->AsVariableProxy();
2148 VectorSlotPair pair =
2149 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002150 PrepareEagerCheckpoint(BeforeId(proxy));
2151 old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair,
2152 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153 break;
2154 }
2155 case NAMED_PROPERTY: {
2156 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002157 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002158 VectorSlotPair pair =
2159 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002160 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002161 old_value = BuildNamedLoad(object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002162 PrepareFrameState(old_value, property->LoadId(),
2163 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002164 break;
2165 }
2166 case KEYED_PROPERTY: {
2167 Node* key = environment()->Top();
2168 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002169 VectorSlotPair pair =
2170 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002171 PrepareEagerCheckpoint(property->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172 old_value = BuildKeyedLoad(object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002173 PrepareFrameState(old_value, property->LoadId(),
2174 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002175 break;
2176 }
2177 case NAMED_SUPER_PROPERTY: {
2178 Node* home_object = environment()->Top();
2179 Node* receiver = environment()->Peek(1);
2180 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2181 VectorSlotPair pair =
2182 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002183 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002184 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002185 PrepareFrameState(old_value, property->LoadId(),
2186 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002187 break;
2188 }
2189 case KEYED_SUPER_PROPERTY: {
2190 Node* key = environment()->Top();
2191 Node* home_object = environment()->Peek(1);
2192 Node* receiver = environment()->Peek(2);
2193 VectorSlotPair pair =
2194 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002195 PrepareEagerCheckpoint(property->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002196 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002197 PrepareFrameState(old_value, property->LoadId(),
2198 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002199 break;
2200 }
2201 }
2202 environment()->Push(old_value);
2203 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 Node* value;
2205 {
2206 FrameStateBeforeAndAfter states(this, expr->value()->id());
2207 Node* right = environment()->Pop();
2208 Node* left = environment()->Pop();
2209 value =
2210 BuildBinaryOp(left, right, expr->binary_op(),
2211 expr->binary_operation()->BinaryOperationFeedbackId());
2212 states.AddToNode(value, expr->binary_operation()->id(),
2213 OutputFrameStateCombine::Push());
2214 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002215 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002216 if (needs_frame_state_before) {
2217 before_store_id = expr->binary_operation()->id();
2218 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 } else {
2220 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002221 if (needs_frame_state_before) {
2222 before_store_id = expr->value()->id();
2223 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002224 }
2225
2226 // Store the value.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002227 PrepareEagerCheckpoint(before_store_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002228 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002229 VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002230 switch (assign_type) {
2231 case VARIABLE: {
2232 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002233 BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
Ben Murdoch61f157c2016-09-16 13:49:30 +01002234 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002235 break;
2236 }
2237 case NAMED_PROPERTY: {
2238 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002239 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2240 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002241 PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002242 break;
2243 }
2244 case KEYED_PROPERTY: {
2245 Node* key = environment()->Pop();
2246 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002247 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002248 PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002249 break;
2250 }
2251 case NAMED_SUPER_PROPERTY: {
2252 Node* home_object = environment()->Pop();
2253 Node* receiver = environment()->Pop();
2254 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2255 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002256 PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002257 break;
2258 }
2259 case KEYED_SUPER_PROPERTY: {
2260 Node* key = environment()->Pop();
2261 Node* home_object = environment()->Pop();
2262 Node* receiver = environment()->Pop();
2263 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002264 PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002265 break;
2266 }
2267 }
2268
2269 ast_context()->ProduceValue(value);
2270}
2271
2272
2273void AstGraphBuilder::VisitYield(Yield* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01002274 // Generator functions are supported only by going through Ignition first.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002275 SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002276 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2277}
2278
2279
2280void AstGraphBuilder::VisitThrow(Throw* expr) {
2281 VisitForValue(expr->exception());
2282 Node* exception = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002283 Node* value = BuildThrowError(exception, expr->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002284 ast_context()->ProduceValue(value);
2285}
2286
2287
2288void AstGraphBuilder::VisitProperty(Property* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002289 Node* value = nullptr;
2290 LhsKind property_kind = Property::GetAssignType(expr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002291 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002292 switch (property_kind) {
2293 case VARIABLE:
2294 UNREACHABLE();
2295 break;
2296 case NAMED_PROPERTY: {
2297 VisitForValue(expr->obj());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002298 PrepareEagerCheckpoint(expr->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002299 Node* object = environment()->Pop();
2300 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2301 value = BuildNamedLoad(object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002302 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002303 break;
2304 }
2305 case KEYED_PROPERTY: {
2306 VisitForValue(expr->obj());
2307 VisitForValue(expr->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002308 PrepareEagerCheckpoint(expr->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002309 Node* key = environment()->Pop();
2310 Node* object = environment()->Pop();
2311 value = BuildKeyedLoad(object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002312 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002313 break;
2314 }
2315 case NAMED_SUPER_PROPERTY: {
2316 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2317 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002318 PrepareEagerCheckpoint(expr->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002319 Node* home_object = environment()->Pop();
2320 Node* receiver = environment()->Pop();
2321 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2322 value = BuildNamedSuperLoad(receiver, home_object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002323 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002324 break;
2325 }
2326 case KEYED_SUPER_PROPERTY: {
2327 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2328 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2329 VisitForValue(expr->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002330 PrepareEagerCheckpoint(expr->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002331 Node* key = environment()->Pop();
2332 Node* home_object = environment()->Pop();
2333 Node* receiver = environment()->Pop();
2334 value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002335 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002336 break;
2337 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002339 ast_context()->ProduceValue(value);
2340}
2341
2342
2343void AstGraphBuilder::VisitCall(Call* expr) {
2344 Expression* callee = expr->expression();
2345 Call::CallType call_type = expr->GetCallType(isolate());
2346
2347 // Prepare the callee and the receiver to the function call. This depends on
2348 // the semantics of the underlying call type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002349 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2350 Node* receiver_value = nullptr;
2351 Node* callee_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352 bool possibly_eval = false;
2353 switch (call_type) {
2354 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002355 VariableProxy* proxy = callee->AsVariableProxy();
2356 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002357 PrepareEagerCheckpoint(BeforeId(proxy));
2358 callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
2359 pair, OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002360 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002361 receiver_value = jsgraph()->UndefinedConstant();
2362 break;
2363 }
2364 case Call::LOOKUP_SLOT_CALL: {
2365 Variable* variable = callee->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002366 DCHECK(variable->location() == VariableLocation::LOOKUP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002367 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002368 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002369 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2370 Node* pair = NewNode(op, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002371 callee_value = NewNode(common()->Projection(0), pair);
2372 receiver_value = NewNode(common()->Projection(1), pair);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002373 PrepareFrameState(pair, expr->LookupId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002374 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002375 break;
2376 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002377 case Call::NAMED_PROPERTY_CALL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002378 Property* property = callee->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002379 VectorSlotPair feedback =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002380 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002381 VisitForValue(property->obj());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002382 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002383 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2384 Node* object = environment()->Top();
2385 callee_value = BuildNamedLoad(object, name, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002386 PrepareFrameState(callee_value, property->LoadId(),
2387 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002388 // 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;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002392 receiver_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002393 break;
2394 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002395 case Call::KEYED_PROPERTY_CALL: {
2396 Property* property = callee->AsProperty();
2397 VectorSlotPair feedback =
2398 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2399 VisitForValue(property->obj());
2400 VisitForValue(property->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002401 PrepareEagerCheckpoint(property->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002402 Node* key = environment()->Pop();
2403 Node* object = environment()->Top();
2404 callee_value = BuildKeyedLoad(object, key, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002405 PrepareFrameState(callee_value, property->LoadId(),
2406 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002407 // Note that a property call requires the receiver to be wrapped into
2408 // an object for sloppy callees. However the receiver is guaranteed
2409 // not to be null or undefined at this point.
2410 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2411 receiver_value = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002412 break;
2413 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002414 case Call::NAMED_SUPER_PROPERTY_CALL: {
2415 Property* property = callee->AsProperty();
2416 SuperPropertyReference* super_ref =
2417 property->obj()->AsSuperPropertyReference();
2418 VisitForValue(super_ref->home_object());
2419 VisitForValue(super_ref->this_var());
2420 Node* home = environment()->Peek(1);
2421 Node* object = environment()->Top();
2422 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Ben Murdoch61f157c2016-09-16 13:49:30 +01002423 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002424 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002425 PrepareFrameState(callee_value, property->LoadId(),
2426 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002427 // Note that a property call requires the receiver to be wrapped into
2428 // an object for sloppy callees. Since the receiver is not the target of
2429 // the load, it could very well be null or undefined at this point.
2430 receiver_value = environment()->Pop();
2431 environment()->Drop(1);
2432 break;
2433 }
2434 case Call::KEYED_SUPER_PROPERTY_CALL: {
2435 Property* property = callee->AsProperty();
2436 SuperPropertyReference* super_ref =
2437 property->obj()->AsSuperPropertyReference();
2438 VisitForValue(super_ref->home_object());
2439 VisitForValue(super_ref->this_var());
2440 environment()->Push(environment()->Top()); // Duplicate this_var.
2441 environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
2442 VisitForValue(property->key());
2443 Node* key = environment()->Pop();
2444 Node* home = environment()->Pop();
2445 Node* object = environment()->Pop();
Ben Murdoch61f157c2016-09-16 13:49:30 +01002446 PrepareEagerCheckpoint(property->key()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002447 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002448 PrepareFrameState(callee_value, property->LoadId(),
2449 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002450 // Note that a property call requires the receiver to be wrapped into
2451 // an object for sloppy callees. Since the receiver is not the target of
2452 // the load, it could very well be null or undefined at this point.
2453 receiver_value = environment()->Pop();
2454 environment()->Drop(1);
2455 break;
2456 }
2457 case Call::SUPER_CALL:
2458 return VisitCallSuper(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002459 case Call::POSSIBLY_EVAL_CALL:
2460 possibly_eval = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002461 if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2462 Variable* variable = callee->AsVariableProxy()->var();
2463 Node* name = jsgraph()->Constant(variable->name());
2464 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002465 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2466 Node* pair = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467 callee_value = NewNode(common()->Projection(0), pair);
2468 receiver_value = NewNode(common()->Projection(1), pair);
2469 PrepareFrameState(pair, expr->LookupId(),
2470 OutputFrameStateCombine::Push(2));
2471 break;
2472 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002473 // Fall through.
2474 case Call::OTHER_CALL:
2475 VisitForValue(callee);
2476 callee_value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002477 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478 receiver_value = jsgraph()->UndefinedConstant();
2479 break;
2480 }
2481
2482 // The callee and the receiver both have to be pushed onto the operand stack
2483 // before arguments are being evaluated.
2484 environment()->Push(callee_value);
2485 environment()->Push(receiver_value);
2486
2487 // Evaluate all arguments to the function call,
2488 ZoneList<Expression*>* args = expr->arguments();
2489 VisitForValues(args);
2490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002491 // Resolve callee for a potential direct eval call. This block will mutate the
2492 // callee value pushed onto the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002493 if (possibly_eval && args->length() > 0) {
2494 int arg_count = args->length();
2495
2496 // Extract callee and source string from the environment.
2497 Node* callee = environment()->Peek(arg_count + 1);
2498 Node* source = environment()->Peek(arg_count - 1);
2499
2500 // Create node to ask for help resolving potential eval call. This will
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002501 // provide a fully resolved callee to patch into the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002502 Node* function = GetFunctionClosure();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002503 Node* language = jsgraph()->Constant(language_mode());
Ben Murdochc5610432016-08-08 18:44:38 +01002504 Node* eval_scope_position =
2505 jsgraph()->Constant(current_scope()->start_position());
2506 Node* eval_position = jsgraph()->Constant(expr->position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002508 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Ben Murdochc5610432016-08-08 18:44:38 +01002509 Node* new_callee = NewNode(op, callee, source, function, language,
2510 eval_scope_position, eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002511 PrepareFrameState(new_callee, expr->EvalId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002512 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002514 // Patch callee on the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002515 environment()->Poke(arg_count + 1, new_callee);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002516 }
2517
2518 // Create node to perform the function call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002519 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2520 const Operator* call = javascript()->CallFunction(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002521 args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002522 PrepareEagerCheckpoint(expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002523 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002524 environment()->Push(value->InputAt(0)); // The callee passed to the call.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002525 PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002526 environment()->Drop(1);
2527 ast_context()->ProduceValue(value);
2528}
2529
2530
2531void AstGraphBuilder::VisitCallSuper(Call* expr) {
2532 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2533 DCHECK_NOT_NULL(super);
2534
2535 // Prepare the callee to the super call.
2536 VisitForValue(super->this_function_var());
2537 Node* this_function = environment()->Pop();
2538 const Operator* op =
2539 javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2540 Node* super_function = NewNode(op, this_function);
2541 environment()->Push(super_function);
2542
2543 // Evaluate all arguments to the super call.
2544 ZoneList<Expression*>* args = expr->arguments();
2545 VisitForValues(args);
2546
2547 // The new target is loaded from the {new.target} variable.
2548 VisitForValue(super->new_target_var());
2549
2550 // Create node to perform the super call.
2551 const Operator* call =
2552 javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002553 PrepareEagerCheckpoint(super->new_target_var()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002554 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002555 PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556 ast_context()->ProduceValue(value);
2557}
2558
2559
2560void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2561 VisitForValue(expr->expression());
2562
2563 // Evaluate all arguments to the construct call.
2564 ZoneList<Expression*>* args = expr->arguments();
2565 VisitForValues(args);
2566
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002567 // The baseline compiler doesn't push the new.target, so we need to record
2568 // the frame state before the push.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002569 PrepareEagerCheckpoint(args->is_empty() ? expr->expression()->id()
2570 : args->last()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002571
2572 // The new target is the same as the callee.
2573 environment()->Push(environment()->Peek(args->length()));
2574
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002575 // Create node to perform the construct call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002576 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2577 const Operator* call =
2578 javascript()->CallConstruct(args->length() + 2, feedback);
2579 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002580 PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002581 ast_context()->ProduceValue(value);
2582}
2583
2584
2585void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002586 // The callee and the receiver both have to be pushed onto the operand stack
2587 // before arguments are being evaluated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002588 Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2589 Node* receiver_value = jsgraph()->UndefinedConstant();
2590
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002591 environment()->Push(callee_value);
2592 environment()->Push(receiver_value);
2593
2594 // Evaluate all arguments to the JS runtime call.
2595 ZoneList<Expression*>* args = expr->arguments();
2596 VisitForValues(args);
2597
2598 // Create node to perform the JS runtime call.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002599 const Operator* call = javascript()->CallFunction(args->length() + 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002600 PrepareEagerCheckpoint(expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002601 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002602 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603 ast_context()->ProduceValue(value);
2604}
2605
2606
2607void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002608 // Handle calls to runtime functions implemented in JavaScript separately as
2609 // the call follows JavaScript ABI and the callee is statically unknown.
2610 if (expr->is_jsruntime()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002611 return VisitCallJSRuntime(expr);
2612 }
2613
2614 // Evaluate all arguments to the runtime call.
2615 ZoneList<Expression*>* args = expr->arguments();
2616 VisitForValues(args);
2617
2618 // Create node to perform the runtime call.
Ben Murdochda12d292016-06-02 14:46:10 +01002619 Runtime::FunctionId functionId = expr->function()->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002620 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002621 PrepareEagerCheckpoint(expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002622 Node* value = ProcessArguments(call, args->length());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002623 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002624 ast_context()->ProduceValue(value);
2625}
2626
2627
2628void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2629 switch (expr->op()) {
2630 case Token::DELETE:
2631 return VisitDelete(expr);
2632 case Token::VOID:
2633 return VisitVoid(expr);
2634 case Token::TYPEOF:
2635 return VisitTypeof(expr);
2636 case Token::NOT:
2637 return VisitNot(expr);
2638 default:
2639 UNREACHABLE();
2640 }
2641}
2642
2643
2644void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002645 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002646
2647 // Left-hand side can only be a property, a global or a variable slot.
2648 Property* property = expr->expression()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002649 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002650
2651 // Reserve space for result of postfix operation.
2652 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002653 if (is_postfix && assign_type != VARIABLE) {
2654 environment()->Push(jsgraph()->ZeroConstant());
2655 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002656
2657 // Evaluate LHS expression and get old value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002658 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002659 int stack_depth = -1;
2660 switch (assign_type) {
2661 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002662 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2663 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002664 PrepareEagerCheckpoint(BeforeId(proxy));
2665 old_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
2666 pair, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002667 stack_depth = 0;
2668 break;
2669 }
2670 case NAMED_PROPERTY: {
2671 VisitForValue(property->obj());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002672 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002673 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002674 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002675 VectorSlotPair pair =
2676 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002677 old_value = BuildNamedLoad(object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002678 PrepareFrameState(old_value, property->LoadId(),
2679 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002680 stack_depth = 1;
2681 break;
2682 }
2683 case KEYED_PROPERTY: {
2684 VisitForValue(property->obj());
2685 VisitForValue(property->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002686 PrepareEagerCheckpoint(property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002687 Node* key = environment()->Top();
2688 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002689 VectorSlotPair pair =
2690 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002691 old_value = BuildKeyedLoad(object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002692 PrepareFrameState(old_value, property->LoadId(),
2693 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002694 stack_depth = 2;
2695 break;
2696 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002697 case NAMED_SUPER_PROPERTY: {
2698 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2699 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002700 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002701 Node* home_object = environment()->Top();
2702 Node* receiver = environment()->Peek(1);
2703 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2704 VectorSlotPair pair =
2705 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2706 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002707 PrepareFrameState(old_value, property->LoadId(),
2708 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002709 stack_depth = 2;
2710 break;
2711 }
2712 case KEYED_SUPER_PROPERTY: {
2713 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2714 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2715 VisitForValue(property->key());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002716 PrepareEagerCheckpoint(property->obj()->id());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002717 Node* key = environment()->Top();
2718 Node* home_object = environment()->Peek(1);
2719 Node* receiver = environment()->Peek(2);
2720 VectorSlotPair pair =
2721 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2722 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002723 PrepareFrameState(old_value, property->LoadId(),
2724 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002725 stack_depth = 3;
2726 break;
2727 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002728 }
2729
2730 // Convert old value into a number.
Ben Murdochda12d292016-06-02 14:46:10 +01002731 old_value = NewNode(javascript()->ToNumber(), old_value);
2732 PrepareFrameState(old_value, expr->ToNumberId(),
2733 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734
2735 // Create a proper eager frame state for the stores.
2736 environment()->Push(old_value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002737 FrameStateBeforeAndAfter binop_states(this, expr->ToNumberId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002738 old_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002739
2740 // Save result for postfix expressions at correct stack depth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002741 if (is_postfix) {
2742 if (assign_type != VARIABLE) {
2743 environment()->Poke(stack_depth, old_value);
2744 } else {
2745 environment()->Push(old_value);
2746 }
2747 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002748
2749 // Create node to perform +1/-1 operation.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002750 // TODO(bmeurer): Cleanup this feedback/bailout mess!
2751 Node* value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
2752 expr->binary_op(), expr->CountBinOpFeedbackId());
2753 // This should never deoptimize because we have converted to number before.
2754 binop_states.AddToNode(value, BailoutId::None(),
2755 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002756
2757 // Store the value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002758 VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002759 switch (assign_type) {
2760 case VARIABLE: {
2761 Variable* variable = expr->expression()->AsVariableProxy()->var();
2762 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 BuildVariableAssignment(variable, value, expr->op(), feedback,
Ben Murdoch61f157c2016-09-16 13:49:30 +01002764 expr->AssignmentId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002765 environment()->Pop();
2766 break;
2767 }
2768 case NAMED_PROPERTY: {
2769 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002770 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2771 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002772 environment()->Push(value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002773 PrepareFrameState(store, expr->AssignmentId(),
2774 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002775 environment()->Pop();
2776 break;
2777 }
2778 case KEYED_PROPERTY: {
2779 Node* key = environment()->Pop();
2780 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002781 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002782 environment()->Push(value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002783 PrepareFrameState(store, expr->AssignmentId(),
2784 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002785 environment()->Pop();
2786 break;
2787 }
2788 case NAMED_SUPER_PROPERTY: {
2789 Node* home_object = environment()->Pop();
2790 Node* receiver = environment()->Pop();
2791 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2792 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2793 environment()->Push(value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002794 PrepareFrameState(store, expr->AssignmentId(),
2795 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002796 environment()->Pop();
2797 break;
2798 }
2799 case KEYED_SUPER_PROPERTY: {
2800 Node* key = environment()->Pop();
2801 Node* home_object = environment()->Pop();
2802 Node* receiver = environment()->Pop();
2803 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2804 environment()->Push(value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002805 PrepareFrameState(store, expr->AssignmentId(),
2806 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002807 environment()->Pop();
2808 break;
2809 }
2810 }
2811
2812 // Restore old value for postfix expressions.
2813 if (is_postfix) value = environment()->Pop();
2814
2815 ast_context()->ProduceValue(value);
2816}
2817
2818
2819void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2820 switch (expr->op()) {
2821 case Token::COMMA:
2822 return VisitComma(expr);
2823 case Token::OR:
2824 case Token::AND:
2825 return VisitLogicalExpression(expr);
2826 default: {
2827 VisitForValue(expr->left());
2828 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002829 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002830 Node* right = environment()->Pop();
2831 Node* left = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002832 Node* value = BuildBinaryOp(left, right, expr->op(),
2833 expr->BinaryOperationFeedbackId());
2834 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002835 ast_context()->ProduceValue(value);
2836 }
2837 }
2838}
2839
Ben Murdochda12d292016-06-02 14:46:10 +01002840void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
2841 Expression* sub_expr,
2842 Node* nil_value) {
2843 const Operator* op = nullptr;
2844 switch (expr->op()) {
2845 case Token::EQ:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002846 op = javascript()->Equal(CompareOperationHints::Any());
Ben Murdochda12d292016-06-02 14:46:10 +01002847 break;
2848 case Token::EQ_STRICT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002849 op = javascript()->StrictEqual(CompareOperationHints::Any());
Ben Murdochda12d292016-06-02 14:46:10 +01002850 break;
2851 default:
2852 UNREACHABLE();
2853 }
2854 VisitForValue(sub_expr);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002855 PrepareEagerCheckpoint(sub_expr->id());
Ben Murdochda12d292016-06-02 14:46:10 +01002856 Node* value_to_compare = environment()->Pop();
2857 Node* value = NewNode(op, value_to_compare, nil_value);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002858 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochda12d292016-06-02 14:46:10 +01002859 return ast_context()->ProduceValue(value);
2860}
2861
2862void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
2863 Expression* sub_expr,
2864 Handle<String> check) {
2865 VisitTypeofExpression(sub_expr);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002866 PrepareEagerCheckpoint(sub_expr->id());
Ben Murdochda12d292016-06-02 14:46:10 +01002867 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002868 Node* value = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
2869 typeof_arg, jsgraph()->Constant(check));
2870 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochda12d292016-06-02 14:46:10 +01002871 return ast_context()->ProduceValue(value);
2872}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002873
2874void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Ben Murdochda12d292016-06-02 14:46:10 +01002875 // Check for a few fast cases. The AST visiting behavior must be in sync
2876 // with the full codegen: We don't push both left and right values onto
2877 // the expression stack when one side is a special-case literal.
2878 Expression* sub_expr = nullptr;
2879 Handle<String> check;
2880 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
2881 return VisitLiteralCompareTypeof(expr, sub_expr, check);
2882 }
2883 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
2884 return VisitLiteralCompareNil(expr, sub_expr,
2885 jsgraph()->UndefinedConstant());
2886 }
2887 if (expr->IsLiteralCompareNull(&sub_expr)) {
2888 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
2889 }
2890
Ben Murdoch61f157c2016-09-16 13:49:30 +01002891 CompareOperationHints hints;
2892 if (!type_hint_analysis_ ||
2893 !type_hint_analysis_->GetCompareOperationHints(
2894 expr->CompareOperationFeedbackId(), &hints)) {
2895 hints = CompareOperationHints::Any();
2896 }
2897
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002898 const Operator* op;
2899 switch (expr->op()) {
2900 case Token::EQ:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002901 op = javascript()->Equal(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002902 break;
2903 case Token::NE:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002904 op = javascript()->NotEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002905 break;
2906 case Token::EQ_STRICT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002907 op = javascript()->StrictEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002908 break;
2909 case Token::NE_STRICT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002910 op = javascript()->StrictNotEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002911 break;
2912 case Token::LT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002913 op = javascript()->LessThan(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002914 break;
2915 case Token::GT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002916 op = javascript()->GreaterThan(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002917 break;
2918 case Token::LTE:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002919 op = javascript()->LessThanOrEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002920 break;
2921 case Token::GTE:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002922 op = javascript()->GreaterThanOrEqual(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002923 break;
2924 case Token::INSTANCEOF:
2925 op = javascript()->InstanceOf();
2926 break;
2927 case Token::IN:
2928 op = javascript()->HasProperty();
2929 break;
2930 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002931 op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002932 UNREACHABLE();
2933 }
2934 VisitForValue(expr->left());
2935 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002936 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002937 Node* right = environment()->Pop();
2938 Node* left = environment()->Pop();
2939 Node* value = NewNode(op, left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002940 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002941 ast_context()->ProduceValue(value);
2942}
2943
2944
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002945void AstGraphBuilder::VisitSpread(Spread* expr) {
2946 // Handled entirely by the parser itself.
2947 UNREACHABLE();
2948}
2949
2950
2951void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2952 // Handled entirely by the parser itself.
2953 UNREACHABLE();
2954}
2955
2956
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002957void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2958 Node* value = GetFunctionClosure();
2959 ast_context()->ProduceValue(value);
2960}
2961
2962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002963void AstGraphBuilder::VisitSuperPropertyReference(
2964 SuperPropertyReference* expr) {
2965 Node* value = BuildThrowUnsupportedSuperError(expr->id());
2966 ast_context()->ProduceValue(value);
2967}
2968
2969
2970void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2971 // Handled by VisitCall
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002972 UNREACHABLE();
2973}
2974
2975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002976void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2977 // Handled entirely in VisitSwitch.
2978 UNREACHABLE();
2979}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002980
2981
2982void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002983 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002984 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002985 if (globals()->empty()) return;
2986 int array_index = 0;
2987 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2988 static_cast<int>(globals()->size()), TENURED);
2989 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochc5610432016-08-08 18:44:38 +01002990 int encoded_flags = info()->GetDeclareGlobalsFlags();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002991 Node* flags = jsgraph()->Constant(encoded_flags);
2992 Node* pairs = jsgraph()->Constant(data);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002993 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002994 Node* call = NewNode(op, pairs, flags);
2995 PrepareFrameState(call, BailoutId::Declarations());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002996 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002997}
2998
2999
3000void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003001 if (stmt == nullptr) return;
3002 Visit(stmt);
3003}
3004
3005
3006void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
3007 ContextScope scope(this, s, context);
3008 DCHECK(s->declarations()->is_empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003009 Visit(stmt);
3010}
3011
3012
3013void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003014 LoopBuilder* loop) {
3015 ControlScopeForIteration scope(this, stmt, loop);
3016 if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
3017 Node* node = NewNode(javascript()->StackCheck());
3018 PrepareFrameState(node, stmt->StackCheckId());
3019 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003020 Visit(stmt->body());
3021}
3022
3023
3024void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
3025 Node* value;
3026 if (expr->expression()->IsVariableProxy()) {
3027 // Delete of an unqualified identifier is only allowed in classic mode but
3028 // deleting "this" is allowed in all language modes.
3029 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003030 // Delete of an unqualified identifier is disallowed in strict mode but
3031 // "delete this" is allowed.
3032 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003033 value = BuildVariableDelete(variable, expr->id(),
3034 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003035 } else if (expr->expression()->IsProperty()) {
3036 Property* property = expr->expression()->AsProperty();
3037 VisitForValue(property->obj());
3038 VisitForValue(property->key());
3039 Node* key = environment()->Pop();
3040 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003041 value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003042 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003043 } else {
3044 VisitForEffect(expr->expression());
3045 value = jsgraph()->TrueConstant();
3046 }
3047 ast_context()->ProduceValue(value);
3048}
3049
3050
3051void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
3052 VisitForEffect(expr->expression());
3053 Node* value = jsgraph()->UndefinedConstant();
3054 ast_context()->ProduceValue(value);
3055}
3056
Ben Murdochda12d292016-06-02 14:46:10 +01003057void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
3058 if (expr->IsVariableProxy()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003059 // Typeof does not throw a reference error on global variables, hence we
3060 // perform a non-contextual load in case the operand is a variable proxy.
Ben Murdochda12d292016-06-02 14:46:10 +01003061 VariableProxy* proxy = expr->AsVariableProxy();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003062 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch61f157c2016-09-16 13:49:30 +01003063 PrepareEagerCheckpoint(BeforeId(proxy));
Ben Murdochda12d292016-06-02 14:46:10 +01003064 Node* load =
Ben Murdoch61f157c2016-09-16 13:49:30 +01003065 BuildVariableLoad(proxy->var(), expr->id(), pair,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003066 OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Ben Murdochda12d292016-06-02 14:46:10 +01003067 environment()->Push(load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003068 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01003069 VisitForValue(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003070 }
Ben Murdochda12d292016-06-02 14:46:10 +01003071}
3072
3073void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
3074 VisitTypeofExpression(expr->expression());
3075 Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003076 ast_context()->ProduceValue(value);
3077}
3078
3079
3080void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3081 VisitForValue(expr->expression());
3082 Node* operand = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003083 Node* input = BuildToBoolean(operand, expr->expression()->test_id());
3084 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
3085 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003086 ast_context()->ProduceValue(value);
3087}
3088
3089
3090void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3091 VisitForEffect(expr->left());
3092 Visit(expr->right());
3093 ast_context()->ReplaceValue();
3094}
3095
3096
3097void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3098 bool is_logical_and = expr->op() == Token::AND;
3099 IfBuilder compare_if(this);
3100 VisitForValue(expr->left());
3101 Node* condition = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003102 compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003103 compare_if.Then();
3104 if (is_logical_and) {
3105 environment()->Pop();
3106 Visit(expr->right());
3107 } else if (ast_context()->IsEffect()) {
3108 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003109 } else if (ast_context()->IsTest()) {
3110 environment()->Poke(0, jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003111 }
3112 compare_if.Else();
3113 if (!is_logical_and) {
3114 environment()->Pop();
3115 Visit(expr->right());
3116 } else if (ast_context()->IsEffect()) {
3117 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003118 } else if (ast_context()->IsTest()) {
3119 environment()->Poke(0, jsgraph()->FalseConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003120 }
3121 compare_if.End();
3122 ast_context()->ReplaceValue();
3123}
3124
3125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003126LanguageMode AstGraphBuilder::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003127 return current_scope()->language_mode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003128}
3129
3130
3131VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003132 FeedbackVectorSlot slot) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +01003133 return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003134}
3135
3136
Ben Murdoch097c5b22016-05-18 11:27:45 +01003137void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003138 Visit(node->expression());
3139}
3140
3141
3142namespace {
3143
3144// Limit of context chain length to which inline check is possible.
3145const int kMaxCheckDepth = 30;
3146
3147// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3148const uint32_t kFullCheckRequired = -1;
3149
3150} // namespace
3151
3152
3153uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3154 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3155 bool found_eval_scope = false;
3156 uint32_t check_depths = 0;
3157 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3158 if (s->num_heap_slots() <= 0) continue;
3159 // TODO(mstarzinger): If we have reached an eval scope, we check all
3160 // extensions from this point. Replicated from full-codegen, figure out
3161 // whether this is still needed. If not, drop {found_eval_scope} below.
3162 if (s->is_eval_scope()) found_eval_scope = true;
3163 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3164 int depth = current_scope()->ContextChainLength(s);
3165 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3166 check_depths |= 1 << depth;
3167 }
3168 return check_depths;
3169}
3170
3171
3172uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3173 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3174 uint32_t check_depths = 0;
3175 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3176 if (s->num_heap_slots() <= 0) continue;
3177 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3178 int depth = current_scope()->ContextChainLength(s);
3179 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3180 check_depths |= 1 << depth;
3181 if (s == variable->scope()) break;
3182 }
3183 return check_depths;
3184}
3185
3186
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003187Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3188 DCHECK(environment()->stack_height() >= arity);
3189 Node** all = info()->zone()->NewArray<Node*>(arity);
3190 for (int i = arity - 1; i >= 0; --i) {
3191 all[i] = environment()->Pop();
3192 }
3193 Node* value = NewNode(op, arity, all);
3194 return value;
3195}
3196
3197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003198Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3199 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003200
3201 // Allocate a new local context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003202 Node* local_context = scope->is_script_scope()
3203 ? BuildLocalScriptContext(scope)
3204 : BuildLocalFunctionContext(scope);
3205
3206 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3207 Node* receiver = environment()->RawParameterLookup(0);
3208 // Context variable (at bottom of the context chain).
3209 Variable* variable = scope->receiver();
3210 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3211 const Operator* op = javascript()->StoreContext(0, variable->index());
3212 NewNode(op, local_context, receiver);
3213 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003214
3215 // Copy parameters into context if necessary.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003216 int num_parameters = scope->num_parameters();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003217 for (int i = 0; i < num_parameters; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003218 Variable* variable = scope->parameter(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003219 if (!variable->IsContextSlot()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003220 Node* parameter = environment()->RawParameterLookup(i + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003221 // Context variable (at bottom of the context chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003222 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003223 const Operator* op = javascript()->StoreContext(0, variable->index());
3224 NewNode(op, local_context, parameter);
3225 }
3226
3227 return local_context;
3228}
3229
3230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003231Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
Ben Murdochc5610432016-08-08 18:44:38 +01003232 DCHECK(scope->is_function_scope() || scope->is_eval_scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003233
3234 // Allocate a new local context.
3235 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3236 const Operator* op = javascript()->CreateFunctionContext(slot_count);
3237 Node* local_context = NewNode(op, GetFunctionClosure());
3238
3239 return local_context;
3240}
3241
3242
3243Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3244 DCHECK(scope->is_script_scope());
3245
3246 // Allocate a new local context.
3247 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3248 const Operator* op = javascript()->CreateScriptContext(scope_info);
3249 Node* local_context = NewNode(op, GetFunctionClosure());
3250 PrepareFrameState(local_context, BailoutId::ScriptContext(),
3251 OutputFrameStateCombine::Push());
3252
3253 return local_context;
3254}
3255
3256
3257Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3258 DCHECK(scope->is_block_scope());
3259
3260 // Allocate a new local context.
3261 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3262 const Operator* op = javascript()->CreateBlockContext(scope_info);
3263 Node* local_context = NewNode(op, GetFunctionClosureForContext());
3264
3265 return local_context;
3266}
3267
3268
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003269Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003270 if (arguments == nullptr) return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003271
3272 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003273 CreateArgumentsType type =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003274 is_strict(language_mode()) || !info()->has_simple_parameters()
Ben Murdoch097c5b22016-05-18 11:27:45 +01003275 ? CreateArgumentsType::kUnmappedArguments
3276 : CreateArgumentsType::kMappedArguments;
3277 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003278 Node* object = NewNode(op, GetFunctionClosure());
3279 PrepareFrameState(object, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003281 // Assign the object to the {arguments} variable. This should never lazy
3282 // deopt, so it is fine to send invalid bailout id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003283 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003284 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
Ben Murdoch61f157c2016-09-16 13:49:30 +01003285 BailoutId::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003286 return object;
3287}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003289
3290Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3291 if (rest == nullptr) return nullptr;
3292
3293 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003294 CreateArgumentsType type = CreateArgumentsType::kRestParameter;
3295 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003296 Node* object = NewNode(op, GetFunctionClosure());
3297 PrepareFrameState(object, BailoutId::None());
3298
3299 // Assign the object to the {rest} variable. This should never lazy
3300 // deopt, so it is fine to send invalid bailout id.
3301 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003302 BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
Ben Murdoch61f157c2016-09-16 13:49:30 +01003303 BailoutId::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003304 return object;
3305}
3306
3307
3308Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3309 if (this_function_var == nullptr) return nullptr;
3310
3311 // Retrieve the closure we were called with.
3312 Node* this_function = GetFunctionClosure();
3313
3314 // Assign the object to the {.this_function} variable. This should never lazy
3315 // deopt, so it is fine to send invalid bailout id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003316 BuildVariableAssignment(this_function_var, this_function, Token::INIT,
Ben Murdoch61f157c2016-09-16 13:49:30 +01003317 VectorSlotPair(), BailoutId::None());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003318 return this_function;
3319}
3320
3321
3322Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3323 if (new_target_var == nullptr) return nullptr;
3324
3325 // Retrieve the new target we were called with.
3326 Node* object = GetNewTarget();
3327
3328 // Assign the object to the {new.target} variable. This should never lazy
3329 // deopt, so it is fine to send invalid bailout id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003330 BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
Ben Murdoch61f157c2016-09-16 13:49:30 +01003331 BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003332 return object;
3333}
3334
3335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003336Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3337 Node* not_hole,
3338 BailoutId bailout_id) {
3339 IfBuilder hole_check(this);
3340 Node* the_hole = jsgraph()->TheHoleConstant();
Ben Murdoch61f157c2016-09-16 13:49:30 +01003341 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3342 value, the_hole);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003343 hole_check.If(check);
3344 hole_check.Then();
3345 Node* error = BuildThrowReferenceError(variable, bailout_id);
3346 environment()->Push(error);
3347 hole_check.Else();
3348 environment()->Push(not_hole);
3349 hole_check.End();
3350 return environment()->Pop();
3351}
3352
3353
3354Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3355 Node* for_hole,
3356 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003357 IfBuilder hole_check(this);
3358 Node* the_hole = jsgraph()->TheHoleConstant();
Ben Murdoch61f157c2016-09-16 13:49:30 +01003359 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3360 value, the_hole);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003361 hole_check.If(check);
3362 hole_check.Then();
3363 environment()->Push(for_hole);
3364 hole_check.Else();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003365 Node* error = BuildThrowReferenceError(variable, bailout_id);
3366 environment()->Push(error);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003367 hole_check.End();
3368 return environment()->Pop();
3369}
3370
3371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003372Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3373 BailoutId bailout_id) {
3374 IfBuilder prototype_check(this);
3375 Node* prototype_string =
3376 jsgraph()->Constant(isolate()->factory()->prototype_string());
Ben Murdoch61f157c2016-09-16 13:49:30 +01003377 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3378 name, prototype_string);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003379 prototype_check.If(check);
3380 prototype_check.Then();
3381 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3382 environment()->Push(error);
3383 prototype_check.Else();
3384 environment()->Push(name);
3385 prototype_check.End();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003386 return environment()->Pop();
3387}
3388
3389
3390Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3391 BailoutId bailout_id,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003392 const VectorSlotPair& feedback,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003393 OutputFrameStateCombine combine,
3394 TypeofMode typeof_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003395 Node* the_hole = jsgraph()->TheHoleConstant();
3396 VariableMode mode = variable->mode();
3397 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003398 case VariableLocation::GLOBAL:
3399 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003400 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003401 Handle<Name> name = variable->name();
3402 if (Node* node = TryLoadGlobalConstant(name)) return node;
3403 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003404 PrepareFrameState(value, bailout_id, combine);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003405 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003406 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003407 case VariableLocation::PARAMETER:
3408 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003409 // Local var, const, or let variable.
3410 Node* value = environment()->Lookup(variable);
Ben Murdochc5610432016-08-08 18:44:38 +01003411 if (mode == LET || mode == CONST) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003412 // Perform check for uninitialized let/const variables.
3413 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003414 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003415 } else if (value->opcode() == IrOpcode::kPhi) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003416 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003417 }
3418 }
3419 return value;
3420 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003421 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003422 // Context variable (potentially up the context chain).
3423 int depth = current_scope()->ContextChainLength(variable->scope());
3424 bool immutable = variable->maybe_assigned() == kNotAssigned;
3425 const Operator* op =
3426 javascript()->LoadContext(depth, variable->index(), immutable);
3427 Node* value = NewNode(op, current_context());
3428 // TODO(titzer): initialization checks are redundant for already
3429 // initialized immutable context loads, but only specialization knows.
3430 // Maybe specializer should be a parameter to the graph builder?
Ben Murdochc5610432016-08-08 18:44:38 +01003431 if (mode == LET || mode == CONST) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003432 // Perform check for uninitialized let/const variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003433 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003434 }
3435 return value;
3436 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003437 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003438 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003439 Handle<String> name = variable->name();
Ben Murdoch61f157c2016-09-16 13:49:30 +01003440 if (Node* node = TryLoadDynamicVariable(variable, name, bailout_id,
3441 feedback, combine, typeof_mode)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003442 return node;
3443 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003444 Node* value = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003445 PrepareFrameState(value, bailout_id, combine);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003446 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003447 }
3448 }
3449 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003450 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003451}
3452
3453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003454Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3455 BailoutId bailout_id,
3456 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003457 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003458 case VariableLocation::GLOBAL:
3459 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003460 // Global var, const, or let variable.
3461 Node* global = BuildLoadGlobalObject();
3462 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003463 const Operator* op = javascript()->DeleteProperty(language_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003464 Node* result = NewNode(op, global, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003465 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003466 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003467 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003468 case VariableLocation::PARAMETER:
3469 case VariableLocation::LOCAL:
3470 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003471 // Local var, const, or let variable or context variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003472 return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3473 }
3474 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003475 // Dynamic lookup of context variable (anywhere in the chain).
3476 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003477 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003478 javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
3479 Node* result = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003480 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003481 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003482 }
3483 }
3484 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003485 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003486}
3487
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003488Node* AstGraphBuilder::BuildVariableAssignment(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003489 Variable* variable, Node* value, Token::Value op,
3490 const VectorSlotPair& feedback, BailoutId bailout_id,
Ben Murdoch61f157c2016-09-16 13:49:30 +01003491 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003492 Node* the_hole = jsgraph()->TheHoleConstant();
3493 VariableMode mode = variable->mode();
3494 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003495 case VariableLocation::GLOBAL:
3496 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003497 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003498 Handle<Name> name = variable->name();
3499 Node* store = BuildGlobalStore(name, value, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003500 PrepareFrameState(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003501 return store;
3502 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003503 case VariableLocation::PARAMETER:
3504 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003505 // Local var, const, or let variable.
Ben Murdochc5610432016-08-08 18:44:38 +01003506 if (mode == CONST_LEGACY && op != Token::INIT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003507 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003508 // - exception in strict mode.
3509 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003510 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003511 return BuildThrowConstAssignError(bailout_id);
3512 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003513 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003514 } else if (mode == LET && op == Token::INIT) {
3515 // No initialization check needed because scoping guarantees it. Note
3516 // that we still perform a lookup to keep the variable live, because
3517 // baseline code might contain debug code that inspects the variable.
3518 Node* current = environment()->Lookup(variable);
3519 CHECK_NOT_NULL(current);
3520 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003521 // Perform an initialization check for let declared variables.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003522 Node* current = environment()->Lookup(variable);
3523 if (current->op() == the_hole->op()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003524 return BuildThrowReferenceError(variable, bailout_id);
3525 } else if (current->opcode() == IrOpcode::kPhi) {
3526 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003527 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003528 } else if (mode == CONST && op == Token::INIT) {
3529 // Perform an initialization check for const {this} variables.
3530 // Note that the {this} variable is the only const variable being able
3531 // to trigger bind operations outside the TDZ, via {super} calls.
3532 Node* current = environment()->Lookup(variable);
3533 if (current->op() != the_hole->op() && variable->is_this()) {
3534 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3535 }
3536 } else if (mode == CONST && op != Token::INIT) {
3537 // Assignment to const is exception in all modes.
3538 Node* current = environment()->Lookup(variable);
3539 if (current->op() == the_hole->op()) {
3540 return BuildThrowReferenceError(variable, bailout_id);
3541 } else if (current->opcode() == IrOpcode::kPhi) {
3542 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3543 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003544 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003545 }
3546 environment()->Bind(variable, value);
3547 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003548 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003549 // Context variable (potentially up the context chain).
3550 int depth = current_scope()->ContextChainLength(variable->scope());
Ben Murdochc5610432016-08-08 18:44:38 +01003551 if (mode == CONST_LEGACY && op != Token::INIT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003552 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003553 // - exception in strict mode.
3554 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003555 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003556 return BuildThrowConstAssignError(bailout_id);
3557 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003558 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003559 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003560 // Perform an initialization check for let declared variables.
3561 const Operator* op =
3562 javascript()->LoadContext(depth, variable->index(), false);
3563 Node* current = NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003564 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3565 } else if (mode == CONST && op == Token::INIT) {
3566 // Perform an initialization check for const {this} variables.
3567 // Note that the {this} variable is the only const variable being able
3568 // to trigger bind operations outside the TDZ, via {super} calls.
3569 if (variable->is_this()) {
3570 const Operator* op =
3571 javascript()->LoadContext(depth, variable->index(), false);
3572 Node* current = NewNode(op, current_context());
3573 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3574 }
3575 } else if (mode == CONST && op != Token::INIT) {
3576 // Assignment to const is exception in all modes.
3577 const Operator* op =
3578 javascript()->LoadContext(depth, variable->index(), false);
3579 Node* current = NewNode(op, current_context());
3580 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003581 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003582 }
3583 const Operator* op = javascript()->StoreContext(depth, variable->index());
3584 return NewNode(op, current_context(), value);
3585 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003586 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003587 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch097c5b22016-05-18 11:27:45 +01003588 Handle<Name> name = variable->name();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003589 Node* store = BuildDynamicStore(name, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003590 PrepareFrameState(store, bailout_id, combine);
3591 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003592 }
3593 }
3594 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003595 return nullptr;
3596}
3597
3598
3599Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3600 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003601 const Operator* op = javascript()->LoadProperty(feedback);
3602 Node* node = NewNode(op, object, key, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003603 return node;
3604}
3605
3606
3607Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3608 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003609 const Operator* op = javascript()->LoadNamed(name, feedback);
3610 Node* node = NewNode(op, object, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003611 return node;
3612}
3613
3614
3615Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3616 const VectorSlotPair& feedback) {
3617 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003618 Node* node = NewNode(op, object, key, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003619 return node;
3620}
3621
3622
3623Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3624 Node* value,
3625 const VectorSlotPair& feedback) {
3626 const Operator* op =
3627 javascript()->StoreNamed(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003628 Node* node = NewNode(op, object, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003629 return node;
3630}
3631
3632
3633Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3634 Handle<Name> name,
3635 const VectorSlotPair& feedback) {
3636 Node* name_node = jsgraph()->Constant(name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003637 const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
3638 Node* node = NewNode(op, receiver, home_object, name_node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003639 return node;
3640}
3641
3642
3643Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3644 Node* key,
3645 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003646 const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
3647 Node* node = NewNode(op, receiver, home_object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003648 return node;
3649}
3650
3651
3652Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3653 Node* key, Node* value) {
3654 Runtime::FunctionId function_id = is_strict(language_mode())
3655 ? Runtime::kStoreKeyedToSuper_Strict
3656 : Runtime::kStoreKeyedToSuper_Sloppy;
3657 const Operator* op = javascript()->CallRuntime(function_id, 4);
3658 Node* node = NewNode(op, receiver, home_object, key, value);
3659 return node;
3660}
3661
3662
3663Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3664 Handle<Name> name, Node* value) {
3665 Node* name_node = jsgraph()->Constant(name);
3666 Runtime::FunctionId function_id = is_strict(language_mode())
3667 ? Runtime::kStoreToSuper_Strict
3668 : Runtime::kStoreToSuper_Sloppy;
3669 const Operator* op = javascript()->CallRuntime(function_id, 4);
3670 Node* node = NewNode(op, receiver, home_object, name_node, value);
3671 return node;
3672}
3673
3674
3675Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3676 const VectorSlotPair& feedback,
3677 TypeofMode typeof_mode) {
3678 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003679 Node* node = NewNode(op, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003680 return node;
3681}
3682
3683
3684Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3685 const VectorSlotPair& feedback) {
3686 const Operator* op =
3687 javascript()->StoreGlobal(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003688 Node* node = NewNode(op, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003689 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003690}
3691
3692
Ben Murdoch097c5b22016-05-18 11:27:45 +01003693Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
3694 TypeofMode typeof_mode) {
3695 Node* name_node = jsgraph()->Constant(name);
3696 const Operator* op =
3697 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
3698 ? Runtime::kLoadLookupSlot
3699 : Runtime::kLoadLookupSlotInsideTypeof);
3700 Node* node = NewNode(op, name_node);
3701 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003702}
3703
3704
Ben Murdoch097c5b22016-05-18 11:27:45 +01003705Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
3706 Node* name_node = jsgraph()->Constant(name);
3707 const Operator* op = javascript()->CallRuntime(
3708 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
3709 : Runtime::kStoreLookupSlot_Sloppy);
3710 Node* node = NewNode(op, name_node, value);
3711 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003712}
3713
3714
3715Node* AstGraphBuilder::BuildLoadGlobalObject() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003716 return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003717}
3718
3719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003720Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3721 const Operator* op =
3722 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3723 Node* native_context = NewNode(op, current_context());
3724 return NewNode(javascript()->LoadContext(0, index, true), native_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003725}
3726
3727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003728Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3729 if (Node* node = TryFastToBoolean(input)) return node;
3730 ToBooleanHints hints;
3731 if (!type_hint_analysis_ ||
3732 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3733 hints = ToBooleanHint::kAny;
3734 }
3735 return NewNode(javascript()->ToBoolean(hints), input);
3736}
3737
3738
3739Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3740 if (Node* node = TryFastToName(input)) return node;
3741 Node* name = NewNode(javascript()->ToName(), input);
3742 PrepareFrameState(name, bailout_id);
3743 return name;
3744}
3745
3746
3747Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3748 Node* object = NewNode(javascript()->ToObject(), input);
3749 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3750 return object;
3751}
3752
3753
3754Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3755 ObjectLiteralProperty* property,
3756 int slot_number) {
3757 Expression* expr = property->value();
3758 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3759 Handle<Name> name = isolate()->factory()->home_object_symbol();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003760 VectorSlotPair feedback =
3761 CreateVectorSlotPair(property->GetSlot(slot_number));
3762 Node* store = BuildNamedStore(value, name, home_object, feedback);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003763 PrepareFrameState(store, BailoutId::None(),
3764 OutputFrameStateCombine::Ignore());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003765 return store;
3766}
3767
3768
3769Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003770 const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003771 Node* call = NewNode(op, exception);
3772 PrepareFrameState(call, bailout_id);
3773 Node* control = NewNode(common()->Throw(), call);
3774 UpdateControlDependencyToLeaveFunction(control);
3775 return call;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003776}
3777
3778
3779Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3780 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003781 Node* variable_name = jsgraph()->Constant(variable->name());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003782 const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003783 Node* call = NewNode(op, variable_name);
3784 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003785 Node* control = NewNode(common()->Throw(), call);
3786 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003787 return call;
3788}
3789
3790
3791Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003792 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003793 javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003794 Node* call = NewNode(op);
3795 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003796 Node* control = NewNode(common()->Throw(), call);
3797 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003798 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003799}
3800
3801
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003802Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3803 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003804 javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003805 Node* call = NewNode(op);
3806 PrepareFrameState(call, bailout_id);
3807 Node* control = NewNode(common()->Throw(), call);
3808 UpdateControlDependencyToLeaveFunction(control);
3809 return call;
3810}
3811
3812
3813Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3814 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003815 javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003816 Node* call = NewNode(op);
3817 PrepareFrameState(call, bailout_id);
3818 Node* control = NewNode(common()->Throw(), call);
3819 UpdateControlDependencyToLeaveFunction(control);
3820 return call;
3821}
3822
3823
3824Node* AstGraphBuilder::BuildReturn(Node* return_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003825 // Emit tracing call if requested to do so.
3826 if (FLAG_trace) {
3827 return_value =
3828 NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
3829 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003830 Node* control = NewNode(common()->Return(), return_value);
3831 UpdateControlDependencyToLeaveFunction(control);
3832 return control;
3833}
3834
3835
3836Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003837 NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003838 Node* control = NewNode(common()->Throw(), exception_value);
3839 UpdateControlDependencyToLeaveFunction(control);
3840 return control;
3841}
3842
3843
3844Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3845 TypeFeedbackId feedback_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003846 const Operator* js_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003847 BinaryOperationHints hints;
3848 if (!type_hint_analysis_ ||
3849 !type_hint_analysis_->GetBinaryOperationHints(feedback_id, &hints)) {
3850 hints = BinaryOperationHints::Any();
3851 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003852 switch (op) {
3853 case Token::BIT_OR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003854 js_op = javascript()->BitwiseOr(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003855 break;
3856 case Token::BIT_AND:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003857 js_op = javascript()->BitwiseAnd(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003858 break;
3859 case Token::BIT_XOR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003860 js_op = javascript()->BitwiseXor(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003861 break;
3862 case Token::SHL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003863 js_op = javascript()->ShiftLeft(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003864 break;
3865 case Token::SAR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003866 js_op = javascript()->ShiftRight(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003867 break;
3868 case Token::SHR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003869 js_op = javascript()->ShiftRightLogical(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003870 break;
3871 case Token::ADD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003872 js_op = javascript()->Add(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003873 break;
3874 case Token::SUB:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003875 js_op = javascript()->Subtract(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003876 break;
3877 case Token::MUL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003878 js_op = javascript()->Multiply(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003879 break;
3880 case Token::DIV:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003881 js_op = javascript()->Divide(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003882 break;
3883 case Token::MOD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003884 js_op = javascript()->Modulus(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003885 break;
3886 default:
3887 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003888 js_op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003889 }
3890 return NewNode(js_op, left, right);
3891}
3892
3893
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003894Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3895 // Optimize global constants like "undefined", "Infinity", and "NaN".
3896 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3897 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3898 return nullptr;
3899}
3900
Ben Murdoch61f157c2016-09-16 13:49:30 +01003901Node* AstGraphBuilder::TryLoadDynamicVariable(Variable* variable,
3902 Handle<String> name,
3903 BailoutId bailout_id,
3904 const VectorSlotPair& feedback,
3905 OutputFrameStateCombine combine,
3906 TypeofMode typeof_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003907 VariableMode mode = variable->mode();
3908
3909 if (mode == DYNAMIC_GLOBAL) {
3910 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3911 if (bitset == kFullCheckRequired) return nullptr;
3912
3913 // We are using two blocks to model fast and slow cases.
3914 BlockBuilder fast_block(this);
3915 BlockBuilder slow_block(this);
3916 environment()->Push(jsgraph()->TheHoleConstant());
3917 slow_block.BeginBlock();
3918 environment()->Pop();
3919 fast_block.BeginBlock();
3920
3921 // Perform checks whether the fast mode applies, by looking for any
3922 // extension object which might shadow the optimistic declaration.
3923 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3924 if ((bitset & 1) == 0) continue;
3925 Node* load = NewNode(
3926 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3927 current_context());
Ben Murdoch61f157c2016-09-16 13:49:30 +01003928 Node* check =
3929 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
3930 jsgraph()->TheHoleConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003931 fast_block.BreakUnless(check, BranchHint::kTrue);
3932 }
3933
Ben Murdoch097c5b22016-05-18 11:27:45 +01003934 // Fast case, because variable is not shadowed.
3935 if (Node* constant = TryLoadGlobalConstant(name)) {
3936 environment()->Push(constant);
3937 } else {
3938 // Perform global slot load.
3939 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003940 PrepareFrameState(fast, bailout_id, combine);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003941 environment()->Push(fast);
3942 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003943 slow_block.Break();
3944 environment()->Pop();
3945 fast_block.EndBlock();
3946
3947 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003948 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003949 PrepareFrameState(slow, bailout_id, combine);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003950 environment()->Push(slow);
3951 slow_block.EndBlock();
3952
3953 return environment()->Pop();
3954 }
3955
3956 if (mode == DYNAMIC_LOCAL) {
3957 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3958 if (bitset == kFullCheckRequired) return nullptr;
3959
3960 // We are using two blocks to model fast and slow cases.
3961 BlockBuilder fast_block(this);
3962 BlockBuilder slow_block(this);
3963 environment()->Push(jsgraph()->TheHoleConstant());
3964 slow_block.BeginBlock();
3965 environment()->Pop();
3966 fast_block.BeginBlock();
3967
3968 // Perform checks whether the fast mode applies, by looking for any
3969 // extension object which might shadow the optimistic declaration.
3970 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3971 if ((bitset & 1) == 0) continue;
3972 Node* load = NewNode(
3973 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3974 current_context());
Ben Murdoch61f157c2016-09-16 13:49:30 +01003975 Node* check =
3976 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
3977 jsgraph()->TheHoleConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003978 fast_block.BreakUnless(check, BranchHint::kTrue);
3979 }
3980
3981 // Fast case, because variable is not shadowed. Perform context slot load.
3982 Variable* local = variable->local_if_not_shadowed();
3983 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
Ben Murdoch61f157c2016-09-16 13:49:30 +01003984 Node* fast =
3985 BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003986 environment()->Push(fast);
3987 slow_block.Break();
3988 environment()->Pop();
3989 fast_block.EndBlock();
3990
3991 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003992 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003993 PrepareFrameState(slow, bailout_id, combine);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003994 environment()->Push(slow);
3995 slow_block.EndBlock();
3996
3997 return environment()->Pop();
3998 }
3999
4000 return nullptr;
4001}
4002
4003
4004Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
4005 switch (input->opcode()) {
4006 case IrOpcode::kNumberConstant: {
4007 NumberMatcher m(input);
4008 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
4009 }
4010 case IrOpcode::kHeapConstant: {
4011 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4012 return jsgraph_->BooleanConstant(object->BooleanValue());
4013 }
4014 case IrOpcode::kJSEqual:
4015 case IrOpcode::kJSNotEqual:
4016 case IrOpcode::kJSStrictEqual:
4017 case IrOpcode::kJSStrictNotEqual:
4018 case IrOpcode::kJSLessThan:
4019 case IrOpcode::kJSLessThanOrEqual:
4020 case IrOpcode::kJSGreaterThan:
4021 case IrOpcode::kJSGreaterThanOrEqual:
4022 case IrOpcode::kJSToBoolean:
4023 case IrOpcode::kJSDeleteProperty:
4024 case IrOpcode::kJSHasProperty:
4025 case IrOpcode::kJSInstanceOf:
4026 return input;
4027 default:
4028 break;
4029 }
4030 return nullptr;
4031}
4032
4033
4034Node* AstGraphBuilder::TryFastToName(Node* input) {
4035 switch (input->opcode()) {
4036 case IrOpcode::kHeapConstant: {
4037 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4038 if (object->IsName()) return input;
4039 break;
4040 }
4041 case IrOpcode::kJSToString:
4042 case IrOpcode::kJSToName:
4043 case IrOpcode::kJSTypeOf:
4044 return input;
4045 default:
4046 break;
4047 }
4048 return nullptr;
4049}
4050
4051
4052bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4053 if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4054 info()->set_osr_expr_stack_height(std::max(
4055 environment()->stack_height(), info()->osr_expr_stack_height()));
4056 return true;
4057 }
4058 return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004059}
4060
4061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004062void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4063 OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004064 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4065 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4066
4067 DCHECK_EQ(IrOpcode::kDead,
4068 NodeProperties::GetFrameStateInput(node, 0)->opcode());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004069 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004070 NodeProperties::ReplaceFrameStateInput(
Ben Murdoch097c5b22016-05-18 11:27:45 +01004071 node, 0,
4072 environment()->Checkpoint(ast_id, combine, node_has_exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004073 }
4074}
4075
Ben Murdoch61f157c2016-09-16 13:49:30 +01004076void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
4077 if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) {
4078 // We skip preparing a checkpoint if there already is one the current effect
4079 // dependency. This is just an optimization and not need for correctness.
4080 return;
4081 }
4082 if (ast_id != BailoutId::None()) {
4083 Node* node = NewNode(common()->Checkpoint());
4084 DCHECK_EQ(IrOpcode::kDead,
4085 NodeProperties::GetFrameStateInput(node, 0)->opcode());
4086 NodeProperties::ReplaceFrameStateInput(node, 0,
4087 environment()->Checkpoint(ast_id));
4088 }
4089}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004090
4091BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4092 IterationStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004093 if (loop_assignment_analysis_ == nullptr) return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004094 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004095}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004096
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004097
4098Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4099 if (size > input_buffer_size_) {
4100 size = size + kInputBufferSizeIncrement + input_buffer_size_;
4101 input_buffer_ = local_zone()->NewArray<Node*>(size);
4102 input_buffer_size_ = size;
4103 }
4104 return input_buffer_;
4105}
4106
4107
4108Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4109 Node** value_inputs, bool incomplete) {
4110 DCHECK_EQ(op->ValueInputCount(), value_input_count);
4111
4112 bool has_context = OperatorProperties::HasContextInput(op);
4113 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4114 bool has_control = op->ControlInputCount() == 1;
4115 bool has_effect = op->EffectInputCount() == 1;
4116
4117 DCHECK(op->ControlInputCount() < 2);
4118 DCHECK(op->EffectInputCount() < 2);
4119
4120 Node* result = nullptr;
4121 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4122 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4123 } else {
4124 bool inside_try_scope = try_nesting_level_ > 0;
4125 int input_count_with_deps = value_input_count;
4126 if (has_context) ++input_count_with_deps;
4127 input_count_with_deps += frame_state_count;
4128 if (has_control) ++input_count_with_deps;
4129 if (has_effect) ++input_count_with_deps;
4130 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4131 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4132 Node** current_input = buffer + value_input_count;
4133 if (has_context) {
4134 *current_input++ = current_context();
4135 }
4136 for (int i = 0; i < frame_state_count; i++) {
4137 // The frame state will be inserted later. Here we misuse
4138 // the {Dead} node as a sentinel to be later overwritten
4139 // with the real frame state.
4140 *current_input++ = jsgraph()->Dead();
4141 }
4142 if (has_effect) {
4143 *current_input++ = environment_->GetEffectDependency();
4144 }
4145 if (has_control) {
4146 *current_input++ = environment_->GetControlDependency();
4147 }
4148 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4149 if (!environment()->IsMarkedAsUnreachable()) {
4150 // Update the current control dependency for control-producing nodes.
4151 if (NodeProperties::IsControl(result)) {
4152 environment_->UpdateControlDependency(result);
4153 }
4154 // Update the current effect dependency for effect-producing nodes.
4155 if (result->op()->EffectOutputCount() > 0) {
4156 environment_->UpdateEffectDependency(result);
4157 }
4158 // Add implicit exception continuation for throwing nodes.
4159 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4160 // Conservative prediction whether caught locally.
4161 IfExceptionHint hint = try_catch_nesting_level_ > 0
4162 ? IfExceptionHint::kLocallyCaught
4163 : IfExceptionHint::kLocallyUncaught;
4164 // Copy the environment for the success continuation.
4165 Environment* success_env = environment()->CopyForConditional();
4166 const Operator* op = common()->IfException(hint);
4167 Node* effect = environment()->GetEffectDependency();
4168 Node* on_exception = graph()->NewNode(op, effect, result);
4169 environment_->UpdateControlDependency(on_exception);
4170 environment_->UpdateEffectDependency(on_exception);
4171 execution_control()->ThrowValue(on_exception);
4172 set_environment(success_env);
4173 }
4174 // Add implicit success continuation for throwing nodes.
4175 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4176 const Operator* op = common()->IfSuccess();
4177 Node* on_success = graph()->NewNode(op, result);
4178 environment_->UpdateControlDependency(on_success);
4179 }
4180 }
4181 }
4182
4183 return result;
4184}
4185
4186
4187void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4188 if (environment()->IsMarkedAsUnreachable()) return;
4189 environment()->MarkAsUnreachable();
4190 exit_controls_.push_back(exit);
4191}
4192
4193
4194void AstGraphBuilder::Environment::Merge(Environment* other) {
4195 DCHECK(values_.size() == other->values_.size());
4196 DCHECK(contexts_.size() == other->contexts_.size());
4197
4198 // Nothing to do if the other environment is dead.
4199 if (other->IsMarkedAsUnreachable()) return;
4200
4201 // Resurrect a dead environment by copying the contents of the other one and
4202 // placing a singleton merge as the new control dependency.
4203 if (this->IsMarkedAsUnreachable()) {
4204 Node* other_control = other->control_dependency_;
4205 Node* inputs[] = {other_control};
4206 control_dependency_ =
4207 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4208 effect_dependency_ = other->effect_dependency_;
4209 values_ = other->values_;
4210 contexts_ = other->contexts_;
4211 if (IsLivenessAnalysisEnabled()) {
4212 liveness_block_ =
4213 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4214 }
4215 return;
4216 }
4217
4218 // Record the merge for the local variable liveness calculation.
4219 // For loops, we are connecting a back edge into the existing block;
4220 // for merges, we create a new merged block.
4221 if (IsLivenessAnalysisEnabled()) {
4222 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4223 liveness_block_ =
4224 builder_->liveness_analyzer()->NewBlock(liveness_block());
4225 }
4226 liveness_block()->AddPredecessor(other->liveness_block());
4227 }
4228
4229 // Create a merge of the control dependencies of both environments and update
4230 // the current environment's control dependency accordingly.
4231 Node* control = builder_->MergeControl(this->GetControlDependency(),
4232 other->GetControlDependency());
4233 UpdateControlDependency(control);
4234
4235 // Create a merge of the effect dependencies of both environments and update
4236 // the current environment's effect dependency accordingly.
4237 Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4238 other->GetEffectDependency(), control);
4239 UpdateEffectDependency(effect);
4240
4241 // Introduce Phi nodes for values that have differing input at merge points,
4242 // potentially extending an existing Phi node if possible.
4243 for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4244 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4245 }
4246 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4247 contexts_[i] =
4248 builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4249 }
4250}
4251
4252
4253void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4254 bool is_osr) {
4255 int size = static_cast<int>(values()->size());
4256
4257 Node* control = builder_->NewLoop();
4258 if (assigned == nullptr) {
4259 // Assume that everything is updated in the loop.
4260 for (int i = 0; i < size; ++i) {
4261 values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4262 }
4263 } else {
4264 // Only build phis for those locals assigned in this loop.
4265 for (int i = 0; i < size; ++i) {
4266 if (i < assigned->length() && !assigned->Contains(i)) continue;
4267 Node* phi = builder_->NewPhi(1, values()->at(i), control);
4268 values()->at(i) = phi;
4269 }
4270 }
4271 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4272 UpdateEffectDependency(effect);
4273
4274 // Connect the loop to end via Terminate if it's not marked as unreachable.
4275 if (!IsMarkedAsUnreachable()) {
4276 // Connect the Loop node to end via a Terminate node.
4277 Node* terminate = builder_->graph()->NewNode(
4278 builder_->common()->Terminate(), effect, control);
4279 builder_->exit_controls_.push_back(terminate);
4280 }
4281
4282 if (builder_->info()->is_osr()) {
4283 // Introduce phis for all context values in the case of an OSR graph.
4284 for (size_t i = 0; i < contexts()->size(); ++i) {
4285 Node* context = contexts()->at(i);
4286 contexts()->at(i) = builder_->NewPhi(1, context, control);
4287 }
4288 }
4289
4290 if (is_osr) {
4291 // Merge OSR values as inputs to the phis of the loop.
4292 Graph* graph = builder_->graph();
4293 Node* osr_loop_entry = builder_->graph()->NewNode(
4294 builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4295
4296 builder_->MergeControl(control, osr_loop_entry);
4297 builder_->MergeEffect(effect, osr_loop_entry, control);
4298
4299 for (int i = 0; i < size; ++i) {
4300 Node* value = values()->at(i);
4301 Node* osr_value =
4302 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4303 values()->at(i) = builder_->MergeValue(value, osr_value, control);
4304 }
4305
4306 // Rename all the contexts in the environment.
4307 // The innermost context is the OSR value, and the outer contexts are
4308 // reconstructed by dynamically walking up the context chain.
4309 Node* osr_context = nullptr;
4310 const Operator* op =
4311 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4312 const Operator* op_inner =
4313 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4314 int last = static_cast<int>(contexts()->size() - 1);
4315 for (int i = last; i >= 0; i--) {
4316 Node* context = contexts()->at(i);
4317 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4318 : graph->NewNode(op, osr_context, osr_context,
4319 osr_loop_entry);
4320 contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4321 }
4322 }
4323}
4324
4325
4326Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4327 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4328 Node** buffer = EnsureInputBufferSize(count + 1);
4329 MemsetPointer(buffer, input, count);
4330 buffer[count] = control;
4331 return graph()->NewNode(phi_op, count + 1, buffer, true);
4332}
4333
4334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004335Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4336 const Operator* phi_op = common()->EffectPhi(count);
4337 Node** buffer = EnsureInputBufferSize(count + 1);
4338 MemsetPointer(buffer, input, count);
4339 buffer[count] = control;
4340 return graph()->NewNode(phi_op, count + 1, buffer, true);
4341}
4342
4343
4344Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4345 int inputs = control->op()->ControlInputCount() + 1;
4346 if (control->opcode() == IrOpcode::kLoop) {
4347 // Control node for loop exists, add input.
4348 const Operator* op = common()->Loop(inputs);
4349 control->AppendInput(graph_zone(), other);
4350 NodeProperties::ChangeOp(control, op);
4351 } else if (control->opcode() == IrOpcode::kMerge) {
4352 // Control node for merge exists, add input.
4353 const Operator* op = common()->Merge(inputs);
4354 control->AppendInput(graph_zone(), other);
4355 NodeProperties::ChangeOp(control, op);
4356 } else {
4357 // Control node is a singleton, introduce a merge.
4358 const Operator* op = common()->Merge(inputs);
4359 Node* inputs[] = {control, other};
4360 control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4361 }
4362 return control;
4363}
4364
4365
4366Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4367 int inputs = control->op()->ControlInputCount();
4368 if (value->opcode() == IrOpcode::kEffectPhi &&
4369 NodeProperties::GetControlInput(value) == control) {
4370 // Phi already exists, add input.
4371 value->InsertInput(graph_zone(), inputs - 1, other);
4372 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4373 } else if (value != other) {
4374 // Phi does not exist yet, introduce one.
4375 value = NewEffectPhi(inputs, value, control);
4376 value->ReplaceInput(inputs - 1, other);
4377 }
4378 return value;
4379}
4380
4381
4382Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4383 int inputs = control->op()->ControlInputCount();
4384 if (value->opcode() == IrOpcode::kPhi &&
4385 NodeProperties::GetControlInput(value) == control) {
4386 // Phi already exists, add input.
4387 value->InsertInput(graph_zone(), inputs - 1, other);
4388 NodeProperties::ChangeOp(
4389 value, common()->Phi(MachineRepresentation::kTagged, inputs));
4390 } else if (value != other) {
4391 // Phi does not exist yet, introduce one.
4392 value = NewPhi(inputs, value, control);
4393 value->ReplaceInput(inputs - 1, other);
4394 }
4395 return value;
4396}
4397
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004398} // namespace compiler
4399} // namespace internal
4400} // namespace v8