blob: c70dfbf65062f10110e56a468e21745e89659167 [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
209
210// Helper class for a try-finally control scope. It can record intercepted
211// control-flow commands that cause entry into a finally-block, and re-apply
212// them after again leaving that block. Special tokens are used to identify
213// paths going through the finally-block to dispatch after leaving the block.
214class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
215 public:
216 explicit DeferredCommands(AstGraphBuilder* owner)
217 : owner_(owner), deferred_(owner->local_zone()) {}
218
219 // One recorded control-flow command.
220 struct Entry {
221 Command command; // The command type being applied on this path.
222 Statement* statement; // The target statement for the command or {nullptr}.
223 Node* token; // A token identifying this particular path.
224 };
225
226 // Records a control-flow command while entering the finally-block. This also
227 // generates a new dispatch token that identifies one particular path.
228 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
229 Node* token = NewPathTokenForDeferredCommand();
230 deferred_.push_back({cmd, stmt, token});
231 return token;
232 }
233
234 // Returns the dispatch token to be used to identify the implicit fall-through
235 // path at the end of a try-block into the corresponding finally-block.
236 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
237
238 // Applies all recorded control-flow commands after the finally-block again.
239 // This generates a dynamic dispatch on the token from the entry point.
240 void ApplyDeferredCommands(Node* token, Node* value) {
241 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
242 dispatch.BeginSwitch();
243 for (size_t i = 0; i < deferred_.size(); ++i) {
244 Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
245 dispatch.BeginLabel(static_cast<int>(i), condition);
246 dispatch.EndLabel();
247 }
248 for (size_t i = 0; i < deferred_.size(); ++i) {
249 dispatch.BeginCase(static_cast<int>(i));
250 owner_->execution_control()->PerformCommand(
251 deferred_[i].command, deferred_[i].statement, value);
252 dispatch.EndCase();
253 }
254 dispatch.EndSwitch();
255 }
256
257 protected:
258 Node* NewPathTokenForDeferredCommand() {
259 return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size()));
260 }
261 Node* NewPathTokenForImplicitFallThrough() {
262 return owner_->jsgraph()->Constant(-1);
263 }
264 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
265 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
266 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
267 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
268 }
269
270 private:
271 AstGraphBuilder* owner_;
272 ZoneVector<Entry> deferred_;
273};
274
275
276// Control scope implementation for a BreakableStatement.
277class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
278 public:
279 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
280 ControlBuilder* control)
281 : ControlScope(owner), target_(target), control_(control) {}
282
283 protected:
284 bool Execute(Command cmd, Statement* target, Node* value) override {
285 if (target != target_) return false; // We are not the command target.
286 switch (cmd) {
287 case CMD_BREAK:
288 control_->Break();
289 return true;
290 case CMD_CONTINUE:
291 case CMD_THROW:
292 case CMD_RETURN:
293 break;
294 }
295 return false;
296 }
297
298 private:
299 BreakableStatement* target_;
300 ControlBuilder* control_;
301};
302
303
304// Control scope implementation for an IterationStatement.
305class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
306 public:
307 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
308 LoopBuilder* control)
309 : ControlScope(owner), target_(target), control_(control) {}
310
311 protected:
312 bool Execute(Command cmd, Statement* target, Node* value) override {
313 if (target != target_) return false; // We are not the command target.
314 switch (cmd) {
315 case CMD_BREAK:
316 control_->Break();
317 return true;
318 case CMD_CONTINUE:
319 control_->Continue();
320 return true;
321 case CMD_THROW:
322 case CMD_RETURN:
323 break;
324 }
325 return false;
326 }
327
328 private:
329 BreakableStatement* target_;
330 LoopBuilder* control_;
331};
332
333
334// Control scope implementation for a TryCatchStatement.
335class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
336 public:
337 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
338 : ControlScope(owner), control_(control) {
339 builder()->try_nesting_level_++; // Increment nesting.
340 builder()->try_catch_nesting_level_++;
341 }
342 ~ControlScopeForCatch() {
343 builder()->try_nesting_level_--; // Decrement nesting.
344 builder()->try_catch_nesting_level_--;
345 }
346
347 protected:
348 bool Execute(Command cmd, Statement* target, Node* value) override {
349 switch (cmd) {
350 case CMD_THROW:
351 control_->Throw(value);
352 return true;
353 case CMD_BREAK:
354 case CMD_CONTINUE:
355 case CMD_RETURN:
356 break;
357 }
358 return false;
359 }
360
361 private:
362 TryCatchBuilder* control_;
363};
364
365
366// Control scope implementation for a TryFinallyStatement.
367class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
368 public:
369 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
370 TryFinallyBuilder* control)
371 : ControlScope(owner), commands_(commands), control_(control) {
372 builder()->try_nesting_level_++; // Increment nesting.
373 }
374 ~ControlScopeForFinally() {
375 builder()->try_nesting_level_--; // Decrement nesting.
376 }
377
378 protected:
379 bool Execute(Command cmd, Statement* target, Node* value) override {
380 Node* token = commands_->RecordCommand(cmd, target, value);
381 control_->LeaveTry(token, value);
382 return true;
383 }
384
385 private:
386 DeferredCommands* commands_;
387 TryFinallyBuilder* control_;
388};
389
390
391// Helper for generating before and after frame states.
392class AstGraphBuilder::FrameStateBeforeAndAfter {
393 public:
394 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before)
395 : builder_(builder), frame_state_before_(nullptr) {
396 frame_state_before_ = id_before == BailoutId::None()
397 ? builder_->jsgraph()->EmptyFrameState()
398 : builder_->environment()->Checkpoint(id_before);
399 }
400
401 void AddToNode(
402 Node* node, BailoutId id_after,
403 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) {
404 int count = OperatorProperties::GetFrameStateInputCount(node->op());
405 DCHECK_LE(count, 2);
406
407 if (count >= 1) {
408 // Add the frame state for after the operation.
409 DCHECK_EQ(IrOpcode::kDead,
410 NodeProperties::GetFrameStateInput(node, 0)->opcode());
411
412 Node* frame_state_after =
413 id_after == BailoutId::None()
414 ? builder_->jsgraph()->EmptyFrameState()
415 : builder_->environment()->Checkpoint(id_after, combine);
416
417 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
418 }
419
420 if (count >= 2) {
421 // Add the frame state for before the operation.
422 DCHECK_EQ(IrOpcode::kDead,
423 NodeProperties::GetFrameStateInput(node, 1)->opcode());
424 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
425 }
426 }
427
428 private:
429 AstGraphBuilder* builder_;
430 Node* frame_state_before_;
431};
432
433
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400434AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
436 TypeHintAnalysis* type_hint_analysis)
437 : isolate_(info->isolate()),
438 local_zone_(local_zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 info_(info),
440 jsgraph_(jsgraph),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 environment_(nullptr),
442 ast_context_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400443 globals_(0, local_zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 execution_control_(nullptr),
445 execution_context_(nullptr),
446 try_catch_nesting_level_(0),
447 try_nesting_level_(0),
448 input_buffer_size_(0),
449 input_buffer_(nullptr),
450 exit_controls_(local_zone),
451 loop_assignment_analysis_(loop),
452 type_hint_analysis_(type_hint_analysis),
453 state_values_cache_(jsgraph),
454 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
455 local_zone),
456 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
457 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
458 info->scope()->num_stack_slots(), info->shared_info(),
459 CALL_MAINTAINS_NATIVE_CONTEXT)) {
460 InitializeAstVisitor(info->isolate());
461}
462
463
464Node* AstGraphBuilder::GetFunctionClosureForContext() {
465 Scope* closure_scope = current_scope()->ClosureScope();
466 if (closure_scope->is_script_scope() ||
467 closure_scope->is_module_scope()) {
468 // Contexts nested in the native context have a canonical empty function as
469 // their closure, not the anonymous closure containing the global code.
470 return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
471 } else {
472 DCHECK(closure_scope->is_function_scope());
473 return GetFunctionClosure();
474 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475}
476
477
478Node* AstGraphBuilder::GetFunctionClosure() {
479 if (!function_closure_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 int index = Linkage::kJSCallClosureParamIndex;
481 const Operator* op = common()->Parameter(index, "%closure");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482 Node* node = NewNode(op, graph()->start());
483 function_closure_.set(node);
484 }
485 return function_closure_.get();
486}
487
488
489Node* AstGraphBuilder::GetFunctionContext() {
490 if (!function_context_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 int params = info()->num_parameters_including_this();
492 int index = Linkage::GetJSCallContextParamIndex(params);
493 const Operator* op = common()->Parameter(index, "%context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 Node* node = NewNode(op, graph()->start());
495 function_context_.set(node);
496 }
497 return function_context_.get();
498}
499
500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501Node* AstGraphBuilder::GetNewTarget() {
502 if (!new_target_.is_set()) {
503 int params = info()->num_parameters_including_this();
504 int index = Linkage::GetJSCallNewTargetParamIndex(params);
505 const Operator* op = common()->Parameter(index, "%new.target");
506 Node* node = NewNode(op, graph()->start());
507 new_target_.set(node);
508 }
509 return new_target_.get();
510}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512
513bool AstGraphBuilder::CreateGraph(bool stack_check) {
514 Scope* scope = info()->scope();
515 DCHECK_NOT_NULL(graph());
516
517 // Set up the basic structure of the graph. Outputs for {Start} are the formal
518 // parameters (including the receiver) plus new target, number of arguments,
519 // context and closure.
520 int actual_parameter_count = info()->num_parameters_including_this() + 4;
521 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522
523 // Initialize the top-level environment.
524 Environment env(this, scope, graph()->start());
525 set_environment(&env);
526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 if (info()->is_osr()) {
528 // Use OSR normal entry as the start of the top-level environment.
529 // It will be replaced with {Dead} after typing and optimizations.
530 NewNode(common()->OsrNormalEntry());
531 }
532
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400533 // Initialize the incoming context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 ContextScope incoming(this, scope, GetFunctionContext());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 // Initialize control scope.
537 ControlScope control(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
540 // not {the_hole}, because for derived classes {this} has a TDZ and the
541 // JSConstructStubForDerived magically passes {the_hole} as a receiver.
542 if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
543 env.RawParameterBind(0, jsgraph()->TheHoleConstant());
544 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 // Build local context only if there are context allocated variables.
547 if (info()->num_heap_slots() > 0) {
548 // Push a new inner context scope for the current activation.
549 Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
550 ContextScope top_context(this, scope, inner_context);
551 CreateGraphBody(stack_check);
552 } else {
553 // Simply use the outer function context in building the graph.
554 CreateGraphBody(stack_check);
555 }
556
557 // Finish the basic structure of the graph.
558 DCHECK_NE(0u, exit_controls_.size());
559 int const input_count = static_cast<int>(exit_controls_.size());
560 Node** const inputs = &exit_controls_.front();
561 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
562 graph()->SetEnd(end);
563
564 // Compute local variable liveness information and use it to relax
565 // frame states.
566 ClearNonLiveSlotsInFrameStates();
567
568 // Failures indicated by stack overflow.
569 return !HasStackOverflow();
570}
571
572
573void AstGraphBuilder::CreateGraphBody(bool stack_check) {
574 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575
576 // Build the arguments object if it is used.
577 BuildArgumentsObject(scope->arguments());
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 // Build rest arguments array if it is used.
580 int rest_index;
581 Variable* rest_parameter = scope->rest_parameter(&rest_index);
582 BuildRestArgumentsArray(rest_parameter, rest_index);
583
584 // Build assignment to {.this_function} variable if it is used.
585 BuildThisFunctionVariable(scope->this_function_var());
586
587 // Build assignment to {new.target} variable if it is used.
588 BuildNewTargetVariable(scope->new_target_var());
589
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 // Emit tracing call if requested to do so.
591 if (FLAG_trace) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 }
594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 // Visit illegal re-declaration and bail out if it exists.
596 if (scope->HasIllegalRedeclaration()) {
597 VisitForEffect(scope->GetIllegalRedeclaration());
598 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 }
600
601 // Visit declarations within the function scope.
602 VisitDeclarations(scope->declarations());
603
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 // Build a stack-check before the body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 if (stack_check) {
606 Node* node = NewNode(javascript()->StackCheck());
607 PrepareFrameState(node, BailoutId::FunctionEntry());
608 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609
610 // Visit statements in the function body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 VisitStatements(info()->literal()->body());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612
613 // Emit tracing call if requested to do so.
614 if (FLAG_trace) {
615 // TODO(mstarzinger): Only traces implicit return.
616 Node* return_value = jsgraph()->UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 }
619
620 // Return 'undefined' in case we can fall off the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 BuildReturn(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622}
623
624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
626 if (!FLAG_analyze_environment_liveness ||
627 !info()->is_deoptimization_enabled()) {
628 return;
629 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 NonLiveFrameStateSlotReplacer replacer(
632 &state_values_cache_, jsgraph()->UndefinedConstant(),
633 liveness_analyzer()->local_count(), local_zone());
634 Variable* arguments = info()->scope()->arguments();
635 if (arguments != nullptr && arguments->IsStackAllocated()) {
636 replacer.MarkPermanentlyLive(arguments->index());
637 }
638 liveness_analyzer()->Run(&replacer);
639 if (FLAG_trace_environment_liveness) {
640 OFStream os(stdout);
641 liveness_analyzer()->Print(os);
642 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643}
644
645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646// Gets the bailout id just before reading a variable proxy, but only for
647// unallocated variables.
648static BailoutId BeforeId(VariableProxy* proxy) {
649 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
650 : BailoutId::None();
651}
652
653
654static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
655#if DEBUG
656 const AstRawString* name = scope->parameter(index)->raw_name();
657 if (name && name->length() > 0) {
658 char* data = zone->NewArray<char>(name->length() + 1);
659 data[name->length()] = 0;
660 memcpy(data, name->raw_data(), name->length());
661 return data;
662 }
663#endif
664 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665}
666
667
668AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
669 Scope* scope,
670 Node* control_dependency)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671 : builder_(builder),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 parameters_count_(scope->num_parameters() + 1),
673 locals_count_(scope->num_stack_slots()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 liveness_block_(IsLivenessAnalysisEnabled()
675 ? builder_->liveness_analyzer()->NewBlock()
676 : nullptr),
677 values_(builder_->local_zone()),
678 contexts_(builder_->local_zone()),
679 control_dependency_(control_dependency),
680 effect_dependency_(control_dependency),
681 parameters_node_(nullptr),
682 locals_node_(nullptr),
683 stack_node_(nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
685
686 // Bind the receiver variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687 int param_num = 0;
688 if (builder->info()->is_this_defined()) {
689 const Operator* op = common()->Parameter(param_num++, "%this");
690 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
691 values()->push_back(receiver);
692 } else {
693 values()->push_back(builder->jsgraph()->UndefinedConstant());
694 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695
696 // Bind all parameter variables. The parameter indices are shifted by 1
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 // (receiver is variable index -1 but {Parameter} node index 0 and located at
698 // index 0 in the environment).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 for (int i = 0; i < scope->num_parameters(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
701 const Operator* op = common()->Parameter(param_num++, debug_name);
702 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 values()->push_back(parameter);
704 }
705
706 // Bind all local variables to undefined.
707 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
708 values()->insert(values()->end(), locals_count(), undefined_constant);
709}
710
711
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
713 LivenessAnalyzerBlock* liveness_block)
714 : builder_(copy->builder_),
715 parameters_count_(copy->parameters_count_),
716 locals_count_(copy->locals_count_),
717 liveness_block_(liveness_block),
718 values_(copy->zone()),
719 contexts_(copy->zone()),
720 control_dependency_(copy->control_dependency_),
721 effect_dependency_(copy->effect_dependency_),
722 parameters_node_(copy->parameters_node_),
723 locals_node_(copy->locals_node_),
724 stack_node_(copy->stack_node_) {
725 const size_t kStackEstimate = 7; // optimum from experimentation!
726 values_.reserve(copy->values_.size() + kStackEstimate);
727 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
728 contexts_.reserve(copy->contexts_.size());
729 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
730 copy->contexts_.end());
731}
732
733
734void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
735 DCHECK(variable->IsStackAllocated());
736 if (variable->IsParameter()) {
737 // The parameter indices are shifted by 1 (receiver is variable
738 // index -1 but located at index 0 in the environment).
739 values()->at(variable->index() + 1) = node;
740 } else {
741 DCHECK(variable->IsStackLocal());
742 values()->at(variable->index() + parameters_count_) = node;
743 DCHECK(IsLivenessBlockConsistent());
744 if (liveness_block() != nullptr) {
745 liveness_block()->Bind(variable->index());
746 }
747 }
748}
749
750
751Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
752 DCHECK(variable->IsStackAllocated());
753 if (variable->IsParameter()) {
754 // The parameter indices are shifted by 1 (receiver is variable
755 // index -1 but located at index 0 in the environment).
756 return values()->at(variable->index() + 1);
757 } else {
758 DCHECK(variable->IsStackLocal());
759 DCHECK(IsLivenessBlockConsistent());
760 if (liveness_block() != nullptr) {
761 liveness_block()->Lookup(variable->index());
762 }
763 return values()->at(variable->index() + parameters_count_);
764 }
765}
766
767
768void AstGraphBuilder::Environment::MarkAllLocalsLive() {
769 DCHECK(IsLivenessBlockConsistent());
770 if (liveness_block() != nullptr) {
771 for (int i = 0; i < locals_count_; i++) {
772 liveness_block()->Lookup(i);
773 }
774 }
775}
776
777
778void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
779 DCHECK_LT(index, parameters_count());
780 values()->at(index) = node;
781}
782
783
784Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
785 DCHECK_LT(index, parameters_count());
786 return values()->at(index);
787}
788
789
790AstGraphBuilder::Environment*
791AstGraphBuilder::Environment::CopyForConditional() {
792 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
793 if (liveness_block() != nullptr) {
794 copy_liveness_block =
795 builder_->liveness_analyzer()->NewBlock(liveness_block());
796 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
797 }
798 return new (zone()) Environment(this, copy_liveness_block);
799}
800
801
802AstGraphBuilder::Environment*
803AstGraphBuilder::Environment::CopyAsUnreachable() {
804 Environment* env = new (zone()) Environment(this, nullptr);
805 env->MarkAsUnreachable();
806 return env;
807}
808
809
810AstGraphBuilder::Environment*
811AstGraphBuilder::Environment::CopyAndShareLiveness() {
812 if (liveness_block() != nullptr) {
813 // Finish the current liveness block before copying.
814 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
815 }
816 Environment* env = new (zone()) Environment(this, liveness_block());
817 return env;
818}
819
820
821AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
822 BitVector* assigned, bool is_osr) {
823 PrepareForLoop(assigned, is_osr);
824 return CopyAndShareLiveness();
825}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826
827
828void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
829 int offset, int count) {
830 bool should_update = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
832 if (*state_values == nullptr || (*state_values)->InputCount() != count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000833 should_update = true;
834 } else {
835 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
836 for (int i = 0; i < count; i++) {
837 if ((*state_values)->InputAt(i) != env_values[i]) {
838 should_update = true;
839 break;
840 }
841 }
842 }
843 if (should_update) {
844 const Operator* op = common()->StateValues(count);
845 (*state_values) = graph()->NewNode(op, count, env_values);
846 }
847}
848
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
851 Node** state_values, int offset, int count) {
852 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
853 *state_values = builder_->state_values_cache_.GetNodeForValues(
854 env_values, static_cast<size_t>(count));
855}
856
857
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858Node* AstGraphBuilder::Environment::Checkpoint(
859 BailoutId ast_id, OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 if (!builder()->info()->is_deoptimization_enabled()) {
861 return builder()->jsgraph()->EmptyFrameState();
862 }
863
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 UpdateStateValues(&parameters_node_, 0, parameters_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000865 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
867 stack_height());
868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 const Operator* op = common()->FrameState(
870 ast_id, combine, builder()->frame_state_function_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000872 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
873 stack_node_, builder()->current_context(),
874 builder()->GetFunctionClosure(),
875 builder()->graph()->start());
876
877 DCHECK(IsLivenessBlockConsistent());
878 if (liveness_block() != nullptr) {
879 liveness_block()->Checkpoint(result);
880 }
881 return result;
882}
883
884
885bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
886 return FLAG_analyze_environment_liveness &&
887 builder()->info()->is_deoptimization_enabled();
888}
889
890
891bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
892 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
893 (liveness_block() == nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894}
895
896
897AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
898 Expression::Context kind)
899 : kind_(kind), owner_(own), outer_(own->ast_context()) {
900 owner()->set_ast_context(this); // Push.
901#ifdef DEBUG
902 original_height_ = environment()->stack_height();
903#endif
904}
905
906
907AstGraphBuilder::AstContext::~AstContext() {
908 owner()->set_ast_context(outer_); // Pop.
909}
910
911
912AstGraphBuilder::AstEffectContext::~AstEffectContext() {
913 DCHECK(environment()->stack_height() == original_height_);
914}
915
916
917AstGraphBuilder::AstValueContext::~AstValueContext() {
918 DCHECK(environment()->stack_height() == original_height_ + 1);
919}
920
921
922AstGraphBuilder::AstTestContext::~AstTestContext() {
923 DCHECK(environment()->stack_height() == original_height_ + 1);
924}
925
926
927void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
928 // The value is ignored.
929}
930
931
932void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
933 environment()->Push(value);
934}
935
936
937void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939}
940
941
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943
944
945Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
946 return environment()->Pop();
947}
948
949
950Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
951 return environment()->Pop();
952}
953
954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955Scope* AstGraphBuilder::current_scope() const {
956 return execution_context_->scope();
957}
958
959
960Node* AstGraphBuilder::current_context() const {
961 return environment()->Context();
962}
963
964
965void AstGraphBuilder::ControlScope::PerformCommand(Command command,
966 Statement* target,
967 Node* value) {
968 Environment* env = environment()->CopyAsUnreachable();
969 ControlScope* current = this;
970 while (current != nullptr) {
971 environment()->TrimStack(current->stack_height());
972 environment()->TrimContextChain(current->context_length());
973 if (current->Execute(command, target, value)) break;
974 current = current->outer_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 builder()->set_environment(env);
977 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000978}
979
980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
982 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000983}
984
985
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
987 PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
988}
989
990
991void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
992 PerformCommand(CMD_RETURN, nullptr, return_value);
993}
994
995
996void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
997 PerformCommand(CMD_THROW, nullptr, exception_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998}
999
1000
1001void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 if (expr == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003 return environment()->Push(jsgraph()->NullConstant());
1004 }
1005 VisitForValue(expr);
1006}
1007
1008
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1010 if (expr == nullptr) {
1011 return environment()->Push(jsgraph()->TheHoleConstant());
1012 }
1013 VisitForValue(expr);
1014}
1015
1016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1018 for (int i = 0; i < exprs->length(); ++i) {
1019 VisitForValue(exprs->at(i));
1020 }
1021}
1022
1023
1024void AstGraphBuilder::VisitForValue(Expression* expr) {
1025 AstValueContext for_value(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001026 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001028 } else {
1029 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 }
1031}
1032
1033
1034void AstGraphBuilder::VisitForEffect(Expression* expr) {
1035 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001038 } else {
1039 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 }
1041}
1042
1043
1044void AstGraphBuilder::VisitForTest(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 AstTestContext for_condition(this, expr->test_id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001046 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001048 } else {
1049 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1050 }
1051}
1052
1053
1054void AstGraphBuilder::Visit(Expression* expr) {
1055 // Reuses enclosing AstContext.
1056 if (!CheckStackOverflow()) {
1057 expr->Accept(this);
1058 } else {
1059 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 }
1061}
1062
1063
1064void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1065 Variable* variable = decl->proxy()->var();
1066 VariableMode mode = decl->mode();
1067 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
1068 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 case VariableLocation::GLOBAL:
1070 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 Handle<Oddball> value = variable->binding_needs_init()
1072 ? isolate()->factory()->the_hole_value()
1073 : isolate()->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001074 globals()->push_back(variable->name());
1075 globals()->push_back(value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076 break;
1077 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 case VariableLocation::PARAMETER:
1079 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001080 if (hole_init) {
1081 Node* value = jsgraph()->TheHoleConstant();
1082 environment()->Bind(variable, value);
1083 }
1084 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 case VariableLocation::CONTEXT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 if (hole_init) {
1087 Node* value = jsgraph()->TheHoleConstant();
1088 const Operator* op = javascript()->StoreContext(0, variable->index());
1089 NewNode(op, current_context(), value);
1090 }
1091 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 UNIMPLEMENTED();
1094 }
1095}
1096
1097
1098void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1099 Variable* variable = decl->proxy()->var();
1100 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 case VariableLocation::GLOBAL:
1102 case VariableLocation::UNALLOCATED: {
1103 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1104 decl->fun(), info()->script(), info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 // Check for stack-overflow exception.
1106 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001107 globals()->push_back(variable->name());
1108 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109 break;
1110 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 case VariableLocation::PARAMETER:
1112 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001113 VisitForValue(decl->fun());
1114 Node* value = environment()->Pop();
1115 environment()->Bind(variable, value);
1116 break;
1117 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001118 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 VisitForValue(decl->fun());
1120 Node* value = environment()->Pop();
1121 const Operator* op = javascript()->StoreContext(0, variable->index());
1122 NewNode(op, current_context(), value);
1123 break;
1124 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126 UNIMPLEMENTED();
1127 }
1128}
1129
1130
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1132 UNREACHABLE();
1133}
1134
1135
1136void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1137 UNREACHABLE();
1138}
1139
1140
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141void AstGraphBuilder::VisitBlock(Block* stmt) {
1142 BlockBuilder block(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 ControlScopeForBreakable scope(this, stmt, &block);
1144 if (stmt->labels() != nullptr) block.BeginBlock();
1145 if (stmt->scope() == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146 // Visit statements in the same scope, no declarations.
1147 VisitStatements(stmt->statements());
1148 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 // Visit declarations and statements in a block scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 if (stmt->scope()->NeedsContext()) {
1151 Node* context = BuildLocalBlockContext(stmt->scope());
1152 ContextScope scope(this, stmt->scope(), context);
1153 VisitDeclarations(stmt->scope()->declarations());
1154 VisitStatements(stmt->statements());
1155 } else {
1156 VisitDeclarations(stmt->scope()->declarations());
1157 VisitStatements(stmt->statements());
1158 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001159 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 if (stmt->labels() != nullptr) block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161}
1162
1163
1164void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1165 VisitForEffect(stmt->expression());
1166}
1167
1168
1169void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1170 // Do nothing.
1171}
1172
1173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1175 SloppyBlockFunctionStatement* stmt) {
1176 Visit(stmt->statement());
1177}
1178
1179
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1181 IfBuilder compare_if(this);
1182 VisitForTest(stmt->condition());
1183 Node* condition = environment()->Pop();
1184 compare_if.If(condition);
1185 compare_if.Then();
1186 Visit(stmt->then_statement());
1187 compare_if.Else();
1188 Visit(stmt->else_statement());
1189 compare_if.End();
1190}
1191
1192
1193void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194 execution_control()->ContinueTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195}
1196
1197
1198void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 execution_control()->BreakTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200}
1201
1202
1203void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1204 VisitForValue(stmt->expression());
1205 Node* result = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 execution_control()->ReturnValue(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207}
1208
1209
1210void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1211 VisitForValue(stmt->expression());
1212 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 Node* object = BuildToObject(value, stmt->ToObjectId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 const Operator* op = javascript()->CreateWithContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 Node* context = NewNode(op, object, GetFunctionClosureForContext());
1216 PrepareFrameState(context, stmt->EntryId());
1217 VisitInScope(stmt->statement(), stmt->scope(), context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001218}
1219
1220
1221void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1222 ZoneList<CaseClause*>* clauses = stmt->cases();
1223 SwitchBuilder compare_switch(this, clauses->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 ControlScopeForBreakable scope(this, stmt, &compare_switch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225 compare_switch.BeginSwitch();
1226 int default_index = -1;
1227
1228 // Keep the switch value on the stack until a case matches.
1229 VisitForValue(stmt->tag());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230
1231 // Iterate over all cases and create nodes for label comparison.
1232 for (int i = 0; i < clauses->length(); i++) {
1233 CaseClause* clause = clauses->at(i);
1234
1235 // The default is not a test, remember index.
1236 if (clause->is_default()) {
1237 default_index = i;
1238 continue;
1239 }
1240
1241 // Create nodes to perform label comparison as if via '==='. The switch
1242 // value is still on the operand stack while the label is evaluated.
1243 VisitForValue(clause->label());
1244 Node* label = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 Node* tag = environment()->Top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 const Operator* op = javascript()->StrictEqual();
1247 Node* condition = NewNode(op, tag, label);
1248 compare_switch.BeginLabel(i, condition);
1249
1250 // Discard the switch value at label match.
1251 environment()->Pop();
1252 compare_switch.EndLabel();
1253 }
1254
1255 // Discard the switch value and mark the default case.
1256 environment()->Pop();
1257 if (default_index >= 0) {
1258 compare_switch.DefaultAt(default_index);
1259 }
1260
1261 // Iterate over all cases and create nodes for case bodies.
1262 for (int i = 0; i < clauses->length(); i++) {
1263 CaseClause* clause = clauses->at(i);
1264 compare_switch.BeginCase(i);
1265 VisitStatements(clause->statements());
1266 compare_switch.EndCase();
1267 }
1268
1269 compare_switch.EndSwitch();
1270}
1271
1272
1273void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1274 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1276 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 while_loop.EndBody();
1278 VisitForTest(stmt->cond());
1279 Node* condition = environment()->Pop();
1280 while_loop.BreakUnless(condition);
1281 while_loop.EndLoop();
1282}
1283
1284
1285void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1286 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001288 VisitForTest(stmt->cond());
1289 Node* condition = environment()->Pop();
1290 while_loop.BreakUnless(condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 while_loop.EndBody();
1293 while_loop.EndLoop();
1294}
1295
1296
1297void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1298 LoopBuilder for_loop(this);
1299 VisitIfNotNull(stmt->init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1301 if (stmt->cond() != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 VisitForTest(stmt->cond());
1303 Node* condition = environment()->Pop();
1304 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 } else {
1306 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001308 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001309 for_loop.EndBody();
1310 VisitIfNotNull(stmt->next());
1311 for_loop.EndLoop();
1312}
1313
1314
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1316 VisitForValue(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001317 Node* object = environment()->Pop();
1318 BlockBuilder for_block(this);
1319 for_block.BeginBlock();
1320 // Check for null or undefined before entering loop.
1321 Node* is_null_cond =
1322 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1323 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1324 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1325 jsgraph()->UndefinedConstant());
1326 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001327 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 // Convert object to jsobject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001329 object = BuildToObject(object, stmt->ToObjectId());
1330 environment()->Push(object);
1331
1332 // Prepare for-in cache.
1333 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
1334 PrepareFrameState(prepare, stmt->EnumId(), OutputFrameStateCombine::Push());
1335 Node* cache_type = NewNode(common()->Projection(0), prepare);
1336 Node* cache_array = NewNode(common()->Projection(1), prepare);
1337 Node* cache_length = NewNode(common()->Projection(2), prepare);
1338
1339 // Construct the rest of the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 environment()->Push(cache_type);
1341 environment()->Push(cache_array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342 environment()->Push(cache_length);
1343 environment()->Push(jsgraph()->ZeroConstant());
1344
1345 // Build the actual loop body.
1346 LoopBuilder for_loop(this);
1347 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001349 // These stack values are renamed in the case of OSR, so reload them
1350 // from the environment.
1351 Node* index = environment()->Peek(0);
1352 Node* cache_length = environment()->Peek(1);
1353 Node* cache_array = environment()->Peek(2);
1354 Node* cache_type = environment()->Peek(3);
1355 Node* object = environment()->Peek(4);
1356
1357 // Check loop termination condition.
1358 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1359 for_loop.BreakWhen(exit_cond);
1360
1361 // Compute the next enumerated value.
1362 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1363 cache_type, index);
1364 PrepareFrameState(value, stmt->FilterId(),
1365 OutputFrameStateCombine::Push());
1366 IfBuilder test_value(this);
1367 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1368 jsgraph()->UndefinedConstant());
1369 test_value.If(test_value_cond, BranchHint::kFalse);
1370 test_value.Then();
1371 test_value.Else();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 // Bind value and do loop body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 VectorSlotPair feedback =
1375 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1376 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1377 stmt->AssignmentId());
1378 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 test_value.End();
1381 index = environment()->Peek(0);
1382 for_loop.EndBody();
1383
1384 // Increment counter and continue.
1385 index = NewNode(javascript()->ForInStep(), index);
1386 environment()->Poke(0, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 for_loop.EndLoop();
1389 environment()->Drop(5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 for_block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392}
1393
1394
1395void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 LoopBuilder for_loop(this);
1397 VisitForEffect(stmt->assign_iterator());
1398 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1399 VisitForEffect(stmt->next_result());
1400 VisitForTest(stmt->result_done());
1401 Node* condition = environment()->Pop();
1402 for_loop.BreakWhen(condition);
1403 VisitForEffect(stmt->assign_each());
1404 VisitIterationBody(stmt, &for_loop);
1405 for_loop.EndBody();
1406 for_loop.EndLoop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407}
1408
1409
1410void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 TryCatchBuilder try_control(this);
1412
1413 // Evaluate the try-block inside a control scope. This simulates a handler
1414 // that is intercepting 'throw' control commands.
1415 try_control.BeginTry();
1416 {
1417 ControlScopeForCatch scope(this, &try_control);
1418 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1419 environment()->Push(current_context());
1420 Visit(stmt->try_block());
1421 environment()->Pop();
1422 }
1423 try_control.EndTry();
1424
1425 // Insert lazy bailout point.
1426 // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
1427 // point. Ideally, we whould not re-enter optimized code when deoptimized
1428 // lazily. Tracked by issue v8:4195.
1429 NewNode(common()->LazyBailout(),
1430 jsgraph()->ZeroConstant(), // dummy target.
1431 environment()->Checkpoint(stmt->HandlerId())); // frame state.
1432
1433 // Clear message object as we enter the catch block.
1434 Node* the_hole = jsgraph()->TheHoleConstant();
1435 NewNode(javascript()->StoreMessage(), the_hole);
1436
1437 // Create a catch scope that binds the exception.
1438 Node* exception = try_control.GetExceptionNode();
1439 Handle<String> name = stmt->variable()->name();
1440 const Operator* op = javascript()->CreateCatchContext(name);
1441 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1442
1443 // Evaluate the catch-block.
1444 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1445 try_control.EndCatch();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446}
1447
1448
1449void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450 TryFinallyBuilder try_control(this);
1451
1452 // We keep a record of all paths that enter the finally-block to be able to
1453 // dispatch to the correct continuation point after the statements in the
1454 // finally-block have been evaluated.
1455 //
1456 // The try-finally construct can enter the finally-block in three ways:
1457 // 1. By exiting the try-block normally, falling through at the end.
1458 // 2. By exiting the try-block with a function-local control flow transfer
1459 // (i.e. through break/continue/return statements).
1460 // 3. By exiting the try-block with a thrown exception.
1461 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1462 ControlScope::DeferredCommands* commands =
1463 new (local_zone()) ControlScope::DeferredCommands(this);
1464
1465 // Evaluate the try-block inside a control scope. This simulates a handler
1466 // that is intercepting all control commands.
1467 try_control.BeginTry();
1468 {
1469 ControlScopeForFinally scope(this, commands, &try_control);
1470 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1471 environment()->Push(current_context());
1472 Visit(stmt->try_block());
1473 environment()->Pop();
1474 }
1475 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1476
1477 // Insert lazy bailout point.
1478 // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
1479 // point. Ideally, we whould not re-enter optimized code when deoptimized
1480 // lazily. Tracked by issue v8:4195.
1481 NewNode(common()->LazyBailout(),
1482 jsgraph()->ZeroConstant(), // dummy target.
1483 environment()->Checkpoint(stmt->HandlerId())); // frame state.
1484
1485 // The result value semantics depend on how the block was entered:
1486 // - ReturnStatement: It represents the return value being returned.
1487 // - ThrowStatement: It represents the exception being thrown.
1488 // - BreakStatement/ContinueStatement: Filled with the hole.
1489 // - Falling through into finally-block: Filled with the hole.
1490 Node* result = try_control.GetResultValueNode();
1491 Node* token = try_control.GetDispatchTokenNode();
1492
1493 // The result value, dispatch token and message is expected on the operand
1494 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1495 Node* message = NewNode(javascript()->LoadMessage());
1496 environment()->Push(token); // TODO(mstarzinger): Cook token!
1497 environment()->Push(result);
1498 environment()->Push(message);
1499
1500 // Clear message object as we enter the finally block.
1501 Node* the_hole = jsgraph()->TheHoleConstant();
1502 NewNode(javascript()->StoreMessage(), the_hole);
1503
1504 // Evaluate the finally-block.
1505 Visit(stmt->finally_block());
1506 try_control.EndFinally();
1507
1508 // The result value, dispatch token and message is restored from the operand
1509 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1510 message = environment()->Pop();
1511 result = environment()->Pop();
1512 token = environment()->Pop(); // TODO(mstarzinger): Uncook token!
1513 NewNode(javascript()->StoreMessage(), message);
1514
1515 // Dynamic dispatch after the finally-block.
1516 commands->ApplyDeferredCommands(token, result);
1517
1518 // TODO(mstarzinger): Remove bailout once everything works.
1519 if (!FLAG_turbo_try_finally) SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520}
1521
1522
1523void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001524 Node* node =
1525 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 PrepareFrameState(node, stmt->DebugBreakId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527 environment()->MarkAllLocalsLive();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528}
1529
1530
1531void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001532 // Find or build a shared function info.
1533 Handle<SharedFunctionInfo> shared_info =
1534 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1535 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536
1537 // Create node to instantiate a new closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001538 PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1539 const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1540 Node* value = NewNode(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 ast_context()->ProduceValue(value);
1542}
1543
1544
1545void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 // Visit declarations and class literal in a block scope.
1547 if (expr->scope()->ContextLocalCount() > 0) {
1548 Node* context = BuildLocalBlockContext(expr->scope());
1549 ContextScope scope(this, expr->scope(), context);
1550 VisitDeclarations(expr->scope()->declarations());
1551 VisitClassLiteralContents(expr);
1552 } else {
1553 VisitDeclarations(expr->scope()->declarations());
1554 VisitClassLiteralContents(expr);
1555 }
1556}
1557
1558
1559void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
1560 Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name())
1561 : jsgraph()->UndefinedConstant();
1562
1563 // The class name is expected on the operand stack.
1564 environment()->Push(class_name);
1565 VisitForValueOrTheHole(expr->extends());
1566 VisitForValue(expr->constructor());
1567
1568 // Create node to instantiate a new class.
1569 Node* constructor = environment()->Pop();
1570 Node* extends = environment()->Pop();
1571 Node* name = environment()->Pop();
1572 Node* start = jsgraph()->Constant(expr->start_position());
1573 Node* end = jsgraph()->Constant(expr->end_position());
1574 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 5);
1575 Node* literal = NewNode(opc, name, extends, constructor, start, end);
1576 PrepareFrameState(literal, expr->CreateLiteralId(),
1577 OutputFrameStateCombine::Push());
1578
1579 // The prototype is ensured to exist by Runtime_DefineClass. No access check
1580 // is needed here since the constructor is created by the class literal.
1581 Node* prototype =
1582 BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset);
1583
1584 // The class literal and the prototype are both expected on the operand stack
1585 // during evaluation of the method values.
1586 environment()->Push(literal);
1587 environment()->Push(prototype);
1588
1589 // Create nodes to store method values into the literal.
1590 for (int i = 0; i < expr->properties()->length(); i++) {
1591 ObjectLiteral::Property* property = expr->properties()->at(i);
1592 environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1593
1594 VisitForValue(property->key());
1595 Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1596 environment()->Push(name);
1597
1598 // The static prototype property is read only. We handle the non computed
1599 // property name case in the parser. Since this is the only case where we
1600 // need to check for an own read only property we special case this so we do
1601 // not need to do this for every property.
1602 if (property->is_static() && property->is_computed_name()) {
1603 Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1604 expr->GetIdForProperty(i));
1605 environment()->Push(check);
1606 }
1607
1608 VisitForValue(property->value());
1609 Node* value = environment()->Pop();
1610 Node* key = environment()->Pop();
1611 Node* receiver = environment()->Pop();
1612
1613 BuildSetHomeObject(value, receiver, property);
1614
1615 switch (property->kind()) {
1616 case ObjectLiteral::Property::CONSTANT:
1617 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1618 case ObjectLiteral::Property::PROTOTYPE:
1619 UNREACHABLE();
1620 case ObjectLiteral::Property::COMPUTED: {
1621 const Operator* op =
1622 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3);
1623 NewNode(op, receiver, key, value);
1624 break;
1625 }
1626 case ObjectLiteral::Property::GETTER: {
1627 Node* attr = jsgraph()->Constant(DONT_ENUM);
1628 const Operator* op = javascript()->CallRuntime(
1629 Runtime::kDefineGetterPropertyUnchecked, 4);
1630 NewNode(op, receiver, key, value, attr);
1631 break;
1632 }
1633 case ObjectLiteral::Property::SETTER: {
1634 Node* attr = jsgraph()->Constant(DONT_ENUM);
1635 const Operator* op = javascript()->CallRuntime(
1636 Runtime::kDefineSetterPropertyUnchecked, 4);
1637 NewNode(op, receiver, key, value, attr);
1638 break;
1639 }
1640 }
1641 }
1642
1643 // Set both the prototype and constructor to have fast properties, and also
1644 // freeze them in strong mode.
1645 prototype = environment()->Pop();
1646 literal = environment()->Pop();
1647 const Operator* op =
1648 javascript()->CallRuntime(Runtime::kFinalizeClassDefinition, 2);
1649 literal = NewNode(op, literal, prototype);
1650
1651 // Assign to class variable.
1652 if (expr->class_variable_proxy() != nullptr) {
1653 Variable* var = expr->class_variable_proxy()->var();
1654 FrameStateBeforeAndAfter states(this, BailoutId::None());
1655 VectorSlotPair feedback = CreateVectorSlotPair(
1656 expr->NeedsProxySlot() ? expr->ProxySlot()
1657 : FeedbackVectorSlot::Invalid());
1658 BuildVariableAssignment(var, literal, Token::INIT, feedback,
1659 BailoutId::None(), states);
1660 }
1661 ast_context()->ProduceValue(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001662}
1663
1664
1665void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1666 UNREACHABLE();
1667}
1668
1669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1671 VisitBlock(expr->block());
1672 VisitVariableProxy(expr->result());
1673 ast_context()->ReplaceValue();
1674}
1675
1676
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677void AstGraphBuilder::VisitConditional(Conditional* expr) {
1678 IfBuilder compare_if(this);
1679 VisitForTest(expr->condition());
1680 Node* condition = environment()->Pop();
1681 compare_if.If(condition);
1682 compare_if.Then();
1683 Visit(expr->then_expression());
1684 compare_if.Else();
1685 Visit(expr->else_expression());
1686 compare_if.End();
1687 ast_context()->ReplaceValue();
1688}
1689
1690
1691void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001692 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001693 FrameStateBeforeAndAfter states(this, BeforeId(expr));
1694 Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
1695 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001696 ast_context()->ProduceValue(value);
1697}
1698
1699
1700void AstGraphBuilder::VisitLiteral(Literal* expr) {
1701 Node* value = jsgraph()->Constant(expr->value());
1702 ast_context()->ProduceValue(value);
1703}
1704
1705
1706void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1707 Node* closure = GetFunctionClosure();
1708
1709 // Create node to materialize a regular expression literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001710 const Operator* op = javascript()->CreateLiteralRegExp(
1711 expr->pattern(), expr->flags(), expr->literal_index());
1712 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001713 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001714 ast_context()->ProduceValue(literal);
1715}
1716
1717
1718void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1719 Node* closure = GetFunctionClosure();
1720
1721 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 const Operator* op = javascript()->CreateLiteralObject(
1723 expr->constant_properties(), expr->ComputeFlags(true),
1724 expr->literal_index());
1725 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001726 PrepareFrameState(literal, expr->CreateLiteralId(),
1727 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001728
1729 // The object is expected on the operand stack during computation of the
1730 // property values and is the value of the entire expression.
1731 environment()->Push(literal);
1732
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001733 // Create nodes to store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001734 int property_index = 0;
1735 AccessorTable accessor_table(local_zone());
1736 for (; property_index < expr->properties()->length(); property_index++) {
1737 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1738 if (property->is_computed_name()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001739 if (property->IsCompileTimeValue()) continue;
1740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001741 Literal* key = property->key()->AsLiteral();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 switch (property->kind()) {
1743 case ObjectLiteral::Property::CONSTANT:
1744 UNREACHABLE();
1745 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1746 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1747 // Fall through.
1748 case ObjectLiteral::Property::COMPUTED: {
1749 // It is safe to use [[Put]] here because the boilerplate already
1750 // contains computed properties with an uninitialized value.
1751 if (key->value()->IsInternalizedString()) {
1752 if (property->emit_store()) {
1753 VisitForValue(property->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001754 FrameStateBeforeAndAfter states(this, property->value()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 Node* literal = environment()->Top();
1757 Handle<Name> name = key->AsPropertyName();
1758 VectorSlotPair feedback =
1759 CreateVectorSlotPair(property->GetSlot(0));
1760 Node* store = BuildNamedStore(literal, name, value, feedback);
1761 states.AddToNode(store, key->id(),
1762 OutputFrameStateCombine::Ignore());
1763 BuildSetHomeObject(value, literal, property, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001764 } else {
1765 VisitForEffect(property->value());
1766 }
1767 break;
1768 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001769 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 VisitForValue(property->key());
1771 VisitForValue(property->value());
1772 Node* value = environment()->Pop();
1773 Node* key = environment()->Pop();
1774 Node* receiver = environment()->Pop();
1775 if (property->emit_store()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001776 Node* language = jsgraph()->Constant(SLOPPY);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001777 const Operator* op =
1778 javascript()->CallRuntime(Runtime::kSetProperty, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 Node* set_property = NewNode(op, receiver, key, value, language);
1780 // SetProperty should not lazy deopt on an object literal.
1781 PrepareFrameState(set_property, BailoutId::None());
1782 BuildSetHomeObject(value, receiver, property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001783 }
1784 break;
1785 }
1786 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001787 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001788 VisitForValue(property->value());
1789 Node* value = environment()->Pop();
1790 Node* receiver = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001791 DCHECK(property->emit_store());
1792 const Operator* op =
1793 javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1794 Node* set_prototype = NewNode(op, receiver, value);
1795 // SetPrototype should not lazy deopt on an object literal.
1796 PrepareFrameState(set_prototype,
1797 expr->GetIdForPropertySet(property_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001798 break;
1799 }
1800 case ObjectLiteral::Property::GETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001801 if (property->emit_store()) {
1802 accessor_table.lookup(key)->second->getter = property;
1803 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 break;
1805 case ObjectLiteral::Property::SETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001806 if (property->emit_store()) {
1807 accessor_table.lookup(key)->second->setter = property;
1808 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001809 break;
1810 }
1811 }
1812
1813 // Create nodes to define accessors, using only a single call to the runtime
1814 // for each pair of corresponding getters and setters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001816 for (AccessorTable::Iterator it = accessor_table.begin();
1817 it != accessor_table.end(); ++it) {
1818 VisitForValue(it->first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001819 VisitObjectLiteralAccessor(literal, it->second->getter);
1820 VisitObjectLiteralAccessor(literal, it->second->setter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001821 Node* setter = environment()->Pop();
1822 Node* getter = environment()->Pop();
1823 Node* name = environment()->Pop();
1824 Node* attr = jsgraph()->Constant(NONE);
1825 const Operator* op =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001826 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001827 Node* call = NewNode(op, literal, name, getter, setter, attr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001828 // This should not lazy deopt on a new literal.
1829 PrepareFrameState(call, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830 }
1831
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001832 // Object literals have two parts. The "static" part on the left contains no
1833 // computed property names, and so we can compute its map ahead of time; see
1834 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1835 // with the first computed property name and continues with all properties to
1836 // its right. All the code from above initializes the static component of the
1837 // object literal, and arranges for the map of the result to reflect the
1838 // static order in which the keys appear. For the dynamic properties, we
1839 // compile them into a series of "SetOwnProperty" runtime calls. This will
1840 // preserve insertion order.
1841 for (; property_index < expr->properties()->length(); property_index++) {
1842 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1843
1844 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1845 environment()->Push(environment()->Top()); // Duplicate receiver.
1846 VisitForValue(property->value());
1847 Node* value = environment()->Pop();
1848 Node* receiver = environment()->Pop();
1849 const Operator* op =
1850 javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1851 Node* call = NewNode(op, receiver, value);
1852 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1853 continue;
1854 }
1855
1856 environment()->Push(environment()->Top()); // Duplicate receiver.
1857 VisitForValue(property->key());
1858 Node* name = BuildToName(environment()->Pop(),
1859 expr->GetIdForPropertyName(property_index));
1860 environment()->Push(name);
1861 VisitForValue(property->value());
1862 Node* value = environment()->Pop();
1863 Node* key = environment()->Pop();
1864 Node* receiver = environment()->Pop();
1865 BuildSetHomeObject(value, receiver, property);
1866 switch (property->kind()) {
1867 case ObjectLiteral::Property::CONSTANT:
1868 case ObjectLiteral::Property::COMPUTED:
1869 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1870 Node* attr = jsgraph()->Constant(NONE);
1871 const Operator* op =
1872 javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
1873 Node* call = NewNode(op, receiver, key, value, attr);
1874 PrepareFrameState(call, BailoutId::None());
1875 break;
1876 }
1877 case ObjectLiteral::Property::PROTOTYPE:
1878 UNREACHABLE(); // Handled specially above.
1879 break;
1880 case ObjectLiteral::Property::GETTER: {
1881 Node* attr = jsgraph()->Constant(NONE);
1882 const Operator* op = javascript()->CallRuntime(
1883 Runtime::kDefineGetterPropertyUnchecked, 4);
1884 Node* call = NewNode(op, receiver, key, value, attr);
1885 PrepareFrameState(call, BailoutId::None());
1886 break;
1887 }
1888 case ObjectLiteral::Property::SETTER: {
1889 Node* attr = jsgraph()->Constant(NONE);
1890 const Operator* op = javascript()->CallRuntime(
1891 Runtime::kDefineSetterPropertyUnchecked, 4);
1892 Node* call = NewNode(op, receiver, key, value, attr);
1893 PrepareFrameState(call, BailoutId::None());
1894 break;
1895 }
1896 }
1897 }
1898
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001899 // Transform literals that contain functions to fast properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001900 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901 if (expr->has_function()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001902 const Operator* op =
1903 javascript()->CallRuntime(Runtime::kToFastProperties, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001904 NewNode(op, literal);
1905 }
1906
1907 ast_context()->ProduceValue(environment()->Pop());
1908}
1909
1910
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001911void AstGraphBuilder::VisitObjectLiteralAccessor(
1912 Node* home_object, ObjectLiteralProperty* property) {
1913 if (property == nullptr) {
1914 VisitForValueOrNull(nullptr);
1915 } else {
1916 VisitForValue(property->value());
1917 BuildSetHomeObject(environment()->Top(), home_object, property);
1918 }
1919}
1920
1921
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1923 Node* closure = GetFunctionClosure();
1924
1925 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001926 const Operator* op = javascript()->CreateLiteralArray(
1927 expr->constant_elements(), expr->ComputeFlags(true),
1928 expr->literal_index());
1929 Node* literal = NewNode(op, closure);
1930 PrepareFrameState(literal, expr->CreateLiteralId(),
1931 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001932
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001933 // The array is expected on the operand stack during computation of the
1934 // element values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001935 environment()->Push(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936
1937 // Create nodes to evaluate all the non-constant subexpressions and to store
1938 // them into the newly cloned array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001939 int array_index = 0;
1940 for (; array_index < expr->values()->length(); array_index++) {
1941 Expression* subexpr = expr->values()->at(array_index);
1942 if (subexpr->IsSpread()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001943 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1944
1945 VisitForValue(subexpr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001946 {
1947 FrameStateBeforeAndAfter states(this, subexpr->id());
1948 VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1949 Node* value = environment()->Pop();
1950 Node* index = jsgraph()->Constant(array_index);
1951 Node* literal = environment()->Top();
1952 Node* store = BuildKeyedStore(literal, index, value, pair);
1953 states.AddToNode(store, expr->GetIdForElement(array_index),
1954 OutputFrameStateCombine::Ignore());
1955 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001956 }
1957
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001958 // In case the array literal contains spread expressions it has two parts. The
1959 // first part is the "static" array which has a literal index is handled
1960 // above. The second part is the part after the first spread expression
1961 // (inclusive) and these elements gets appended to the array. Note that the
1962 // number elements an iterable produces is unknown ahead of time.
1963 for (; array_index < expr->values()->length(); array_index++) {
1964 Expression* subexpr = expr->values()->at(array_index);
1965 Node* result;
1966
1967 if (subexpr->IsSpread()) {
1968 VisitForValue(subexpr->AsSpread()->expression());
1969 FrameStateBeforeAndAfter states(this,
1970 subexpr->AsSpread()->expression()->id());
1971 Node* iterable = environment()->Pop();
1972 Node* array = environment()->Pop();
1973 Node* function = BuildLoadNativeContextField(
1974 Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX);
1975 result = NewNode(javascript()->CallFunction(3, language_mode()), function,
1976 array, iterable);
1977 states.AddToNode(result, expr->GetIdForElement(array_index));
1978 } else {
1979 VisitForValue(subexpr);
1980 Node* value = environment()->Pop();
1981 Node* array = environment()->Pop();
1982 const Operator* op =
1983 javascript()->CallRuntime(Runtime::kAppendElement, 2);
1984 result = NewNode(op, array, value);
1985 PrepareFrameState(result, expr->GetIdForElement(array_index));
1986 }
1987
1988 environment()->Push(result);
1989 }
1990
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001991 ast_context()->ProduceValue(environment()->Pop());
1992}
1993
1994
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001995void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
1996 const VectorSlotPair& feedback,
1997 BailoutId bailout_id_before,
1998 BailoutId bailout_id_after) {
1999 DCHECK(expr->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002000
2001 // Left-hand side can only be a property, a global or a variable slot.
2002 Property* property = expr->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002003 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004
2005 // Evaluate LHS expression and store the value.
2006 switch (assign_type) {
2007 case VARIABLE: {
2008 Variable* var = expr->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002009 environment()->Push(value);
2010 FrameStateBeforeAndAfter states(this, bailout_id_before);
2011 value = environment()->Pop();
2012 BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
2013 bailout_id_after, states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002014 break;
2015 }
2016 case NAMED_PROPERTY: {
2017 environment()->Push(value);
2018 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002019 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002020 Node* object = environment()->Pop();
2021 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2023 Node* store = BuildNamedStore(object, name, value, feedback);
2024 states.AddToNode(store, bailout_id_after,
2025 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002026 break;
2027 }
2028 case KEYED_PROPERTY: {
2029 environment()->Push(value);
2030 VisitForValue(property->obj());
2031 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002032 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002033 Node* key = environment()->Pop();
2034 Node* object = environment()->Pop();
2035 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002036 Node* store = BuildKeyedStore(object, key, value, feedback);
2037 states.AddToNode(store, bailout_id_after,
2038 OutputFrameStateCombine::Ignore());
2039 break;
2040 }
2041 case NAMED_SUPER_PROPERTY: {
2042 environment()->Push(value);
2043 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2044 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2045 FrameStateBeforeAndAfter states(this, property->obj()->id());
2046 Node* home_object = environment()->Pop();
2047 Node* receiver = environment()->Pop();
2048 value = environment()->Pop();
2049 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2050 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2051 states.AddToNode(store, bailout_id_after,
2052 OutputFrameStateCombine::Ignore());
2053 break;
2054 }
2055 case KEYED_SUPER_PROPERTY: {
2056 environment()->Push(value);
2057 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2058 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2059 VisitForValue(property->key());
2060 FrameStateBeforeAndAfter states(this, property->key()->id());
2061 Node* key = environment()->Pop();
2062 Node* home_object = environment()->Pop();
2063 Node* receiver = environment()->Pop();
2064 value = environment()->Pop();
2065 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2066 states.AddToNode(store, bailout_id_after,
2067 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002068 break;
2069 }
2070 }
2071}
2072
2073
2074void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002075 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076
2077 // Left-hand side can only be a property, a global or a variable slot.
2078 Property* property = expr->target()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002079 LhsKind assign_type = Property::GetAssignType(property);
2080 bool needs_frame_state_before = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002081
2082 // Evaluate LHS expression.
2083 switch (assign_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002084 case VARIABLE: {
2085 Variable* variable = expr->target()->AsVariableProxy()->var();
2086 if (variable->location() == VariableLocation::PARAMETER ||
2087 variable->location() == VariableLocation::LOCAL ||
2088 variable->location() == VariableLocation::CONTEXT) {
2089 needs_frame_state_before = false;
2090 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002091 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002092 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093 case NAMED_PROPERTY:
2094 VisitForValue(property->obj());
2095 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002096 case KEYED_PROPERTY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002097 VisitForValue(property->obj());
2098 VisitForValue(property->key());
2099 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002100 case NAMED_SUPER_PROPERTY:
2101 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2102 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2103 break;
2104 case KEYED_SUPER_PROPERTY:
2105 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2106 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2107 VisitForValue(property->key());
2108 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002109 }
2110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002111 BailoutId before_store_id = BailoutId::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002112 // Evaluate the value and potentially handle compound assignments by loading
2113 // the left-hand side value and performing a binary operation.
2114 if (expr->is_compound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002115 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002116 switch (assign_type) {
2117 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002118 VariableProxy* proxy = expr->target()->AsVariableProxy();
2119 VectorSlotPair pair =
2120 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002121 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2122 old_value =
2123 BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
2124 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002125 break;
2126 }
2127 case NAMED_PROPERTY: {
2128 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002129 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002130 VectorSlotPair pair =
2131 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002132 FrameStateBeforeAndAfter states(this, property->obj()->id());
2133 old_value = BuildNamedLoad(object, name, pair);
2134 states.AddToNode(old_value, property->LoadId(),
2135 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002136 break;
2137 }
2138 case KEYED_PROPERTY: {
2139 Node* key = environment()->Top();
2140 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002141 VectorSlotPair pair =
2142 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143 FrameStateBeforeAndAfter states(this, property->key()->id());
2144 old_value = BuildKeyedLoad(object, key, pair);
2145 states.AddToNode(old_value, property->LoadId(),
2146 OutputFrameStateCombine::Push());
2147 break;
2148 }
2149 case NAMED_SUPER_PROPERTY: {
2150 Node* home_object = environment()->Top();
2151 Node* receiver = environment()->Peek(1);
2152 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2153 VectorSlotPair pair =
2154 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2155 FrameStateBeforeAndAfter states(this, property->obj()->id());
2156 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2157 states.AddToNode(old_value, property->LoadId(),
2158 OutputFrameStateCombine::Push());
2159 break;
2160 }
2161 case KEYED_SUPER_PROPERTY: {
2162 Node* key = environment()->Top();
2163 Node* home_object = environment()->Peek(1);
2164 Node* receiver = environment()->Peek(2);
2165 VectorSlotPair pair =
2166 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2167 FrameStateBeforeAndAfter states(this, property->key()->id());
2168 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2169 states.AddToNode(old_value, property->LoadId(),
2170 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002171 break;
2172 }
2173 }
2174 environment()->Push(old_value);
2175 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002176 Node* value;
2177 {
2178 FrameStateBeforeAndAfter states(this, expr->value()->id());
2179 Node* right = environment()->Pop();
2180 Node* left = environment()->Pop();
2181 value =
2182 BuildBinaryOp(left, right, expr->binary_op(),
2183 expr->binary_operation()->BinaryOperationFeedbackId());
2184 states.AddToNode(value, expr->binary_operation()->id(),
2185 OutputFrameStateCombine::Push());
2186 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002187 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002188 if (needs_frame_state_before) {
2189 before_store_id = expr->binary_operation()->id();
2190 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002191 } else {
2192 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002193 if (needs_frame_state_before) {
2194 before_store_id = expr->value()->id();
2195 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002196 }
2197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002198 FrameStateBeforeAndAfter store_states(this, before_store_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002199 // Store the value.
2200 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201 VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002202 switch (assign_type) {
2203 case VARIABLE: {
2204 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002205 BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2206 store_states, ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002207 break;
2208 }
2209 case NAMED_PROPERTY: {
2210 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002211 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2212 Node* store = BuildNamedStore(object, name, value, feedback);
2213 store_states.AddToNode(store, expr->id(),
2214 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002215 break;
2216 }
2217 case KEYED_PROPERTY: {
2218 Node* key = environment()->Pop();
2219 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002220 Node* store = BuildKeyedStore(object, key, value, feedback);
2221 store_states.AddToNode(store, expr->id(),
2222 ast_context()->GetStateCombine());
2223 break;
2224 }
2225 case NAMED_SUPER_PROPERTY: {
2226 Node* home_object = environment()->Pop();
2227 Node* receiver = environment()->Pop();
2228 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2229 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2230 store_states.AddToNode(store, expr->id(),
2231 ast_context()->GetStateCombine());
2232 break;
2233 }
2234 case KEYED_SUPER_PROPERTY: {
2235 Node* key = environment()->Pop();
2236 Node* home_object = environment()->Pop();
2237 Node* receiver = environment()->Pop();
2238 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2239 store_states.AddToNode(store, expr->id(),
2240 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002241 break;
2242 }
2243 }
2244
2245 ast_context()->ProduceValue(value);
2246}
2247
2248
2249void AstGraphBuilder::VisitYield(Yield* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002250 // TODO(turbofan): Implement yield here.
2251 SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002252 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2253}
2254
2255
2256void AstGraphBuilder::VisitThrow(Throw* expr) {
2257 VisitForValue(expr->exception());
2258 Node* exception = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002259 Node* value = BuildThrowError(exception, expr->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002260 ast_context()->ProduceValue(value);
2261}
2262
2263
2264void AstGraphBuilder::VisitProperty(Property* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002265 Node* value = nullptr;
2266 LhsKind property_kind = Property::GetAssignType(expr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002267 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002268 switch (property_kind) {
2269 case VARIABLE:
2270 UNREACHABLE();
2271 break;
2272 case NAMED_PROPERTY: {
2273 VisitForValue(expr->obj());
2274 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2275 Node* object = environment()->Pop();
2276 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2277 value = BuildNamedLoad(object, name, pair);
2278 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2279 break;
2280 }
2281 case KEYED_PROPERTY: {
2282 VisitForValue(expr->obj());
2283 VisitForValue(expr->key());
2284 FrameStateBeforeAndAfter states(this, expr->key()->id());
2285 Node* key = environment()->Pop();
2286 Node* object = environment()->Pop();
2287 value = BuildKeyedLoad(object, key, pair);
2288 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2289 break;
2290 }
2291 case NAMED_SUPER_PROPERTY: {
2292 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2293 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2294 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2295 Node* home_object = environment()->Pop();
2296 Node* receiver = environment()->Pop();
2297 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2298 value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2299 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2300 break;
2301 }
2302 case KEYED_SUPER_PROPERTY: {
2303 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2304 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2305 VisitForValue(expr->key());
2306 FrameStateBeforeAndAfter states(this, expr->key()->id());
2307 Node* key = environment()->Pop();
2308 Node* home_object = environment()->Pop();
2309 Node* receiver = environment()->Pop();
2310 value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2311 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2312 break;
2313 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002314 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002315 ast_context()->ProduceValue(value);
2316}
2317
2318
2319void AstGraphBuilder::VisitCall(Call* expr) {
2320 Expression* callee = expr->expression();
2321 Call::CallType call_type = expr->GetCallType(isolate());
2322
2323 // Prepare the callee and the receiver to the function call. This depends on
2324 // the semantics of the underlying call type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002325 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2326 Node* receiver_value = nullptr;
2327 Node* callee_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002328 bool possibly_eval = false;
2329 switch (call_type) {
2330 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002331 VariableProxy* proxy = callee->AsVariableProxy();
2332 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002333 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002334 callee_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002335 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2336 pair, OutputFrameStateCombine::Push());
2337 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 receiver_value = jsgraph()->UndefinedConstant();
2339 break;
2340 }
2341 case Call::LOOKUP_SLOT_CALL: {
2342 Variable* variable = callee->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002343 DCHECK(variable->location() == VariableLocation::LOOKUP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002344 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002345 const Operator* op =
2346 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 Node* pair = NewNode(op, current_context(), name);
2348 callee_value = NewNode(common()->Projection(0), pair);
2349 receiver_value = NewNode(common()->Projection(1), pair);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 PrepareFrameState(pair, expr->LookupId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002351 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352 break;
2353 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002354 case Call::NAMED_PROPERTY_CALL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002355 Property* property = callee->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002356 VectorSlotPair feedback =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002357 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002358 VisitForValue(property->obj());
2359 FrameStateBeforeAndAfter states(this, property->obj()->id());
2360 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2361 Node* object = environment()->Top();
2362 callee_value = BuildNamedLoad(object, name, feedback);
2363 states.AddToNode(callee_value, property->LoadId(),
2364 OutputFrameStateCombine::Push());
2365 // Note that a property call requires the receiver to be wrapped into
2366 // an object for sloppy callees. However the receiver is guaranteed
2367 // not to be null or undefined at this point.
2368 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002369 receiver_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370 break;
2371 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002372 case Call::KEYED_PROPERTY_CALL: {
2373 Property* property = callee->AsProperty();
2374 VectorSlotPair feedback =
2375 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2376 VisitForValue(property->obj());
2377 VisitForValue(property->key());
2378 FrameStateBeforeAndAfter states(this, property->key()->id());
2379 Node* key = environment()->Pop();
2380 Node* object = environment()->Top();
2381 callee_value = BuildKeyedLoad(object, key, feedback);
2382 states.AddToNode(callee_value, property->LoadId(),
2383 OutputFrameStateCombine::Push());
2384 // Note that a property call requires the receiver to be wrapped into
2385 // an object for sloppy callees. However the receiver is guaranteed
2386 // not to be null or undefined at this point.
2387 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2388 receiver_value = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002389 break;
2390 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002391 case Call::NAMED_SUPER_PROPERTY_CALL: {
2392 Property* property = callee->AsProperty();
2393 SuperPropertyReference* super_ref =
2394 property->obj()->AsSuperPropertyReference();
2395 VisitForValue(super_ref->home_object());
2396 VisitForValue(super_ref->this_var());
2397 Node* home = environment()->Peek(1);
2398 Node* object = environment()->Top();
2399 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2400 FrameStateBeforeAndAfter states(this, property->obj()->id());
2401 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
2402 states.AddToNode(callee_value, property->LoadId(),
2403 OutputFrameStateCombine::Push());
2404 // Note that a property call requires the receiver to be wrapped into
2405 // an object for sloppy callees. Since the receiver is not the target of
2406 // the load, it could very well be null or undefined at this point.
2407 receiver_value = environment()->Pop();
2408 environment()->Drop(1);
2409 break;
2410 }
2411 case Call::KEYED_SUPER_PROPERTY_CALL: {
2412 Property* property = callee->AsProperty();
2413 SuperPropertyReference* super_ref =
2414 property->obj()->AsSuperPropertyReference();
2415 VisitForValue(super_ref->home_object());
2416 VisitForValue(super_ref->this_var());
2417 environment()->Push(environment()->Top()); // Duplicate this_var.
2418 environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
2419 VisitForValue(property->key());
2420 Node* key = environment()->Pop();
2421 Node* home = environment()->Pop();
2422 Node* object = environment()->Pop();
2423 FrameStateBeforeAndAfter states(this, property->key()->id());
2424 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
2425 states.AddToNode(callee_value, property->LoadId(),
2426 OutputFrameStateCombine::Push());
2427 // 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::SUPER_CALL:
2435 return VisitCallSuper(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002436 case Call::POSSIBLY_EVAL_CALL:
2437 possibly_eval = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002438 if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2439 Variable* variable = callee->AsVariableProxy()->var();
2440 Node* name = jsgraph()->Constant(variable->name());
2441 const Operator* op =
2442 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
2443 Node* pair = NewNode(op, current_context(), name);
2444 callee_value = NewNode(common()->Projection(0), pair);
2445 receiver_value = NewNode(common()->Projection(1), pair);
2446 PrepareFrameState(pair, expr->LookupId(),
2447 OutputFrameStateCombine::Push(2));
2448 break;
2449 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450 // Fall through.
2451 case Call::OTHER_CALL:
2452 VisitForValue(callee);
2453 callee_value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002454 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002455 receiver_value = jsgraph()->UndefinedConstant();
2456 break;
2457 }
2458
2459 // The callee and the receiver both have to be pushed onto the operand stack
2460 // before arguments are being evaluated.
2461 environment()->Push(callee_value);
2462 environment()->Push(receiver_value);
2463
2464 // Evaluate all arguments to the function call,
2465 ZoneList<Expression*>* args = expr->arguments();
2466 VisitForValues(args);
2467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002468 // Resolve callee for a potential direct eval call. This block will mutate the
2469 // callee value pushed onto the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002470 if (possibly_eval && args->length() > 0) {
2471 int arg_count = args->length();
2472
2473 // Extract callee and source string from the environment.
2474 Node* callee = environment()->Peek(arg_count + 1);
2475 Node* source = environment()->Peek(arg_count - 1);
2476
2477 // Create node to ask for help resolving potential eval call. This will
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002478 // provide a fully resolved callee to patch into the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002479 Node* function = GetFunctionClosure();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002480 Node* language = jsgraph()->Constant(language_mode());
2481 Node* position = jsgraph()->Constant(current_scope()->start_position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002482 const Operator* op =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002483 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2484 Node* new_callee =
2485 NewNode(op, callee, source, function, language, position);
2486 PrepareFrameState(new_callee, expr->EvalId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002487 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002489 // Patch callee on the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002490 environment()->Poke(arg_count + 1, new_callee);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002491 }
2492
2493 // Create node to perform the function call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002494 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2495 const Operator* call = javascript()->CallFunction(
2496 args->length() + 2, language_mode(), feedback, receiver_hint);
2497 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002498 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002499 environment()->Push(value->InputAt(0)); // The callee passed to the call.
2500 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2501 environment()->Drop(1);
2502 ast_context()->ProduceValue(value);
2503}
2504
2505
2506void AstGraphBuilder::VisitCallSuper(Call* expr) {
2507 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2508 DCHECK_NOT_NULL(super);
2509
2510 // Prepare the callee to the super call.
2511 VisitForValue(super->this_function_var());
2512 Node* this_function = environment()->Pop();
2513 const Operator* op =
2514 javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2515 Node* super_function = NewNode(op, this_function);
2516 environment()->Push(super_function);
2517
2518 // Evaluate all arguments to the super call.
2519 ZoneList<Expression*>* args = expr->arguments();
2520 VisitForValues(args);
2521
2522 // The new target is loaded from the {new.target} variable.
2523 VisitForValue(super->new_target_var());
2524
2525 // Create node to perform the super call.
2526 const Operator* call =
2527 javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
2528 FrameStateBeforeAndAfter states(this, super->new_target_var()->id());
2529 Node* value = ProcessArguments(call, args->length() + 2);
2530 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002531 ast_context()->ProduceValue(value);
2532}
2533
2534
2535void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2536 VisitForValue(expr->expression());
2537
2538 // Evaluate all arguments to the construct call.
2539 ZoneList<Expression*>* args = expr->arguments();
2540 VisitForValues(args);
2541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002542 // The baseline compiler doesn't push the new.target, so we need to record
2543 // the frame state before the push.
2544 FrameStateBeforeAndAfter states(
2545 this, args->is_empty() ? expr->expression()->id() : args->last()->id());
2546
2547 // The new target is the same as the callee.
2548 environment()->Push(environment()->Peek(args->length()));
2549
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002550 // Create node to perform the construct call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002551 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2552 const Operator* call =
2553 javascript()->CallConstruct(args->length() + 2, feedback);
2554 Node* value = ProcessArguments(call, args->length() + 2);
2555 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556 ast_context()->ProduceValue(value);
2557}
2558
2559
2560void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002561 // The callee and the receiver both have to be pushed onto the operand stack
2562 // before arguments are being evaluated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002563 Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2564 Node* receiver_value = jsgraph()->UndefinedConstant();
2565
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002566 environment()->Push(callee_value);
2567 environment()->Push(receiver_value);
2568
2569 // Evaluate all arguments to the JS runtime call.
2570 ZoneList<Expression*>* args = expr->arguments();
2571 VisitForValues(args);
2572
2573 // Create node to perform the JS runtime call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574 const Operator* call =
2575 javascript()->CallFunction(args->length() + 2, language_mode());
2576 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002577 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002578 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002579 ast_context()->ProduceValue(value);
2580}
2581
2582
2583void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002584 // Handle calls to runtime functions implemented in JavaScript separately as
2585 // the call follows JavaScript ABI and the callee is statically unknown.
2586 if (expr->is_jsruntime()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587 return VisitCallJSRuntime(expr);
2588 }
2589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002590 const Runtime::Function* function = expr->function();
2591
2592 // TODO(mstarzinger): This bailout is a gigantic hack, the owner is ashamed.
2593 if (function->function_id == Runtime::kInlineGeneratorNext ||
2594 function->function_id == Runtime::kInlineGeneratorThrow) {
2595 ast_context()->ProduceValue(jsgraph()->TheHoleConstant());
2596 return SetStackOverflow();
2597 }
2598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002599 // Evaluate all arguments to the runtime call.
2600 ZoneList<Expression*>* args = expr->arguments();
2601 VisitForValues(args);
2602
2603 // Create node to perform the runtime call.
2604 Runtime::FunctionId functionId = function->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002605 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002607 Node* value = ProcessArguments(call, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002608 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002609 ast_context()->ProduceValue(value);
2610}
2611
2612
2613void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2614 switch (expr->op()) {
2615 case Token::DELETE:
2616 return VisitDelete(expr);
2617 case Token::VOID:
2618 return VisitVoid(expr);
2619 case Token::TYPEOF:
2620 return VisitTypeof(expr);
2621 case Token::NOT:
2622 return VisitNot(expr);
2623 default:
2624 UNREACHABLE();
2625 }
2626}
2627
2628
2629void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002630 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002631
2632 // Left-hand side can only be a property, a global or a variable slot.
2633 Property* property = expr->expression()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002634 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002635
2636 // Reserve space for result of postfix operation.
2637 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002638 if (is_postfix && assign_type != VARIABLE) {
2639 environment()->Push(jsgraph()->ZeroConstant());
2640 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002641
2642 // Evaluate LHS expression and get old value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002643 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002644 int stack_depth = -1;
2645 switch (assign_type) {
2646 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002647 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2648 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002649 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002650 old_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002651 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2652 pair, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002653 stack_depth = 0;
2654 break;
2655 }
2656 case NAMED_PROPERTY: {
2657 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002658 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002659 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002660 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002661 VectorSlotPair pair =
2662 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002663 old_value = BuildNamedLoad(object, name, pair);
2664 states.AddToNode(old_value, property->LoadId(),
2665 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002666 stack_depth = 1;
2667 break;
2668 }
2669 case KEYED_PROPERTY: {
2670 VisitForValue(property->obj());
2671 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002672 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002673 Node* key = environment()->Top();
2674 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002675 VectorSlotPair pair =
2676 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002677 old_value = BuildKeyedLoad(object, key, pair);
2678 states.AddToNode(old_value, property->LoadId(),
2679 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002680 stack_depth = 2;
2681 break;
2682 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002683 case NAMED_SUPER_PROPERTY: {
2684 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2685 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2686 FrameStateBeforeAndAfter states(this, property->obj()->id());
2687 Node* home_object = environment()->Top();
2688 Node* receiver = environment()->Peek(1);
2689 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2690 VectorSlotPair pair =
2691 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2692 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2693 states.AddToNode(old_value, property->LoadId(),
2694 OutputFrameStateCombine::Push());
2695 stack_depth = 2;
2696 break;
2697 }
2698 case KEYED_SUPER_PROPERTY: {
2699 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2700 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2701 VisitForValue(property->key());
2702 FrameStateBeforeAndAfter states(this, property->obj()->id());
2703 Node* key = environment()->Top();
2704 Node* home_object = environment()->Peek(1);
2705 Node* receiver = environment()->Peek(2);
2706 VectorSlotPair pair =
2707 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2708 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2709 states.AddToNode(old_value, property->LoadId(),
2710 OutputFrameStateCombine::Push());
2711 stack_depth = 3;
2712 break;
2713 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002714 }
2715
2716 // Convert old value into a number.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002717 if (!is_strong(language_mode())) {
2718 old_value = NewNode(javascript()->ToNumber(), old_value);
2719 PrepareFrameState(old_value, expr->ToNumberId(),
2720 OutputFrameStateCombine::Push());
2721 }
2722
2723 // Create a proper eager frame state for the stores.
2724 environment()->Push(old_value);
2725 FrameStateBeforeAndAfter store_states(this, expr->ToNumberId());
2726 old_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002727
2728 // Save result for postfix expressions at correct stack depth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002729 if (is_postfix) {
2730 if (assign_type != VARIABLE) {
2731 environment()->Poke(stack_depth, old_value);
2732 } else {
2733 environment()->Push(old_value);
2734 }
2735 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002736
2737 // Create node to perform +1/-1 operation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002738 Node* value;
2739 {
2740 // TODO(bmeurer): Cleanup this feedback/bailout mess!
2741 FrameStateBeforeAndAfter states(this, BailoutId::None());
2742 value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
2743 expr->binary_op(), TypeFeedbackId::None());
2744 // This should never deoptimize outside strong mode because otherwise we
2745 // have converted to number before.
2746 states.AddToNode(value, is_strong(language_mode()) ? expr->ToNumberId()
2747 : BailoutId::None(),
2748 OutputFrameStateCombine::Ignore());
2749 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002750
2751 // Store the value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002752 VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002753 switch (assign_type) {
2754 case VARIABLE: {
2755 Variable* variable = expr->expression()->AsVariableProxy()->var();
2756 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 BuildVariableAssignment(variable, value, expr->op(), feedback,
2758 expr->AssignmentId(), store_states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002759 environment()->Pop();
2760 break;
2761 }
2762 case NAMED_PROPERTY: {
2763 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002764 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2765 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002766 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002767 store_states.AddToNode(store, expr->AssignmentId(),
2768 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002769 environment()->Pop();
2770 break;
2771 }
2772 case KEYED_PROPERTY: {
2773 Node* key = environment()->Pop();
2774 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002775 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002776 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002777 store_states.AddToNode(store, expr->AssignmentId(),
2778 OutputFrameStateCombine::Ignore());
2779 environment()->Pop();
2780 break;
2781 }
2782 case NAMED_SUPER_PROPERTY: {
2783 Node* home_object = environment()->Pop();
2784 Node* receiver = environment()->Pop();
2785 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2786 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2787 environment()->Push(value);
2788 store_states.AddToNode(store, expr->AssignmentId(),
2789 OutputFrameStateCombine::Ignore());
2790 environment()->Pop();
2791 break;
2792 }
2793 case KEYED_SUPER_PROPERTY: {
2794 Node* key = environment()->Pop();
2795 Node* home_object = environment()->Pop();
2796 Node* receiver = environment()->Pop();
2797 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2798 environment()->Push(value);
2799 store_states.AddToNode(store, expr->AssignmentId(),
2800 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002801 environment()->Pop();
2802 break;
2803 }
2804 }
2805
2806 // Restore old value for postfix expressions.
2807 if (is_postfix) value = environment()->Pop();
2808
2809 ast_context()->ProduceValue(value);
2810}
2811
2812
2813void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2814 switch (expr->op()) {
2815 case Token::COMMA:
2816 return VisitComma(expr);
2817 case Token::OR:
2818 case Token::AND:
2819 return VisitLogicalExpression(expr);
2820 default: {
2821 VisitForValue(expr->left());
2822 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002823 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002824 Node* right = environment()->Pop();
2825 Node* left = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002826 Node* value = BuildBinaryOp(left, right, expr->op(),
2827 expr->BinaryOperationFeedbackId());
2828 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002829 ast_context()->ProduceValue(value);
2830 }
2831 }
2832}
2833
2834
2835void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2836 const Operator* op;
2837 switch (expr->op()) {
2838 case Token::EQ:
2839 op = javascript()->Equal();
2840 break;
2841 case Token::NE:
2842 op = javascript()->NotEqual();
2843 break;
2844 case Token::EQ_STRICT:
2845 op = javascript()->StrictEqual();
2846 break;
2847 case Token::NE_STRICT:
2848 op = javascript()->StrictNotEqual();
2849 break;
2850 case Token::LT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002851 op = javascript()->LessThan(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002852 break;
2853 case Token::GT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002854 op = javascript()->GreaterThan(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002855 break;
2856 case Token::LTE:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002857 op = javascript()->LessThanOrEqual(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002858 break;
2859 case Token::GTE:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002860 op = javascript()->GreaterThanOrEqual(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002861 break;
2862 case Token::INSTANCEOF:
2863 op = javascript()->InstanceOf();
2864 break;
2865 case Token::IN:
2866 op = javascript()->HasProperty();
2867 break;
2868 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002869 op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002870 UNREACHABLE();
2871 }
2872 VisitForValue(expr->left());
2873 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002874 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002875 Node* right = environment()->Pop();
2876 Node* left = environment()->Pop();
2877 Node* value = NewNode(op, left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002878 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002879 ast_context()->ProduceValue(value);
2880}
2881
2882
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002883void AstGraphBuilder::VisitSpread(Spread* expr) {
2884 // Handled entirely by the parser itself.
2885 UNREACHABLE();
2886}
2887
2888
2889void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2890 // Handled entirely by the parser itself.
2891 UNREACHABLE();
2892}
2893
2894
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002895void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2896 Node* value = GetFunctionClosure();
2897 ast_context()->ProduceValue(value);
2898}
2899
2900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002901void AstGraphBuilder::VisitSuperPropertyReference(
2902 SuperPropertyReference* expr) {
2903 Node* value = BuildThrowUnsupportedSuperError(expr->id());
2904 ast_context()->ProduceValue(value);
2905}
2906
2907
2908void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2909 // Handled by VisitCall
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002910 UNREACHABLE();
2911}
2912
2913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2915 // Handled entirely in VisitSwitch.
2916 UNREACHABLE();
2917}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002918
2919
2920void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002921 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002922 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002923 if (globals()->empty()) return;
2924 int array_index = 0;
2925 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2926 static_cast<int>(globals()->size()), TENURED);
2927 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002928 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
2929 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002930 DeclareGlobalsLanguageMode::encode(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002931 Node* flags = jsgraph()->Constant(encoded_flags);
2932 Node* pairs = jsgraph()->Constant(data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002933 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 2);
2934 Node* call = NewNode(op, pairs, flags);
2935 PrepareFrameState(call, BailoutId::Declarations());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002936 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002937}
2938
2939
2940void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002941 if (stmt == nullptr) return;
2942 Visit(stmt);
2943}
2944
2945
2946void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2947 ContextScope scope(this, s, context);
2948 DCHECK(s->declarations()->is_empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002949 Visit(stmt);
2950}
2951
2952
2953void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002954 LoopBuilder* loop) {
2955 ControlScopeForIteration scope(this, stmt, loop);
2956 if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
2957 Node* node = NewNode(javascript()->StackCheck());
2958 PrepareFrameState(node, stmt->StackCheckId());
2959 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002960 Visit(stmt->body());
2961}
2962
2963
2964void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2965 Node* value;
2966 if (expr->expression()->IsVariableProxy()) {
2967 // Delete of an unqualified identifier is only allowed in classic mode but
2968 // deleting "this" is allowed in all language modes.
2969 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002970 // Delete of an unqualified identifier is disallowed in strict mode but
2971 // "delete this" is allowed.
2972 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002973 value = BuildVariableDelete(variable, expr->id(),
2974 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002975 } else if (expr->expression()->IsProperty()) {
2976 Property* property = expr->expression()->AsProperty();
2977 VisitForValue(property->obj());
2978 VisitForValue(property->key());
2979 Node* key = environment()->Pop();
2980 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002981 value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002982 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002983 } else {
2984 VisitForEffect(expr->expression());
2985 value = jsgraph()->TrueConstant();
2986 }
2987 ast_context()->ProduceValue(value);
2988}
2989
2990
2991void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
2992 VisitForEffect(expr->expression());
2993 Node* value = jsgraph()->UndefinedConstant();
2994 ast_context()->ProduceValue(value);
2995}
2996
2997
2998void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
2999 Node* operand;
3000 if (expr->expression()->IsVariableProxy()) {
3001 // Typeof does not throw a reference error on global variables, hence we
3002 // perform a non-contextual load in case the operand is a variable proxy.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003003 VariableProxy* proxy = expr->expression()->AsVariableProxy();
3004 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003005 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
3006 operand =
3007 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, pair,
3008 OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003009 } else {
3010 VisitForValue(expr->expression());
3011 operand = environment()->Pop();
3012 }
3013 Node* value = NewNode(javascript()->TypeOf(), operand);
3014 ast_context()->ProduceValue(value);
3015}
3016
3017
3018void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3019 VisitForValue(expr->expression());
3020 Node* operand = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003021 Node* input = BuildToBoolean(operand, expr->expression()->test_id());
3022 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
3023 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003024 ast_context()->ProduceValue(value);
3025}
3026
3027
3028void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3029 VisitForEffect(expr->left());
3030 Visit(expr->right());
3031 ast_context()->ReplaceValue();
3032}
3033
3034
3035void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3036 bool is_logical_and = expr->op() == Token::AND;
3037 IfBuilder compare_if(this);
3038 VisitForValue(expr->left());
3039 Node* condition = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003040 compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003041 compare_if.Then();
3042 if (is_logical_and) {
3043 environment()->Pop();
3044 Visit(expr->right());
3045 } else if (ast_context()->IsEffect()) {
3046 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003047 } else if (ast_context()->IsTest()) {
3048 environment()->Poke(0, jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003049 }
3050 compare_if.Else();
3051 if (!is_logical_and) {
3052 environment()->Pop();
3053 Visit(expr->right());
3054 } else if (ast_context()->IsEffect()) {
3055 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003056 } else if (ast_context()->IsTest()) {
3057 environment()->Poke(0, jsgraph()->FalseConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003058 }
3059 compare_if.End();
3060 ast_context()->ReplaceValue();
3061}
3062
3063
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003064LanguageMode AstGraphBuilder::language_mode() const {
3065 return info()->language_mode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003066}
3067
3068
3069VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003070 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003071 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3072}
3073
3074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003075void AstGraphBuilder::VisitRewritableAssignmentExpression(
3076 RewritableAssignmentExpression* node) {
3077 Visit(node->expression());
3078}
3079
3080
3081namespace {
3082
3083// Limit of context chain length to which inline check is possible.
3084const int kMaxCheckDepth = 30;
3085
3086// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3087const uint32_t kFullCheckRequired = -1;
3088
3089} // namespace
3090
3091
3092uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3093 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3094 bool found_eval_scope = false;
3095 uint32_t check_depths = 0;
3096 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3097 if (s->num_heap_slots() <= 0) continue;
3098 // TODO(mstarzinger): If we have reached an eval scope, we check all
3099 // extensions from this point. Replicated from full-codegen, figure out
3100 // whether this is still needed. If not, drop {found_eval_scope} below.
3101 if (s->is_eval_scope()) found_eval_scope = true;
3102 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3103 int depth = current_scope()->ContextChainLength(s);
3104 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3105 check_depths |= 1 << depth;
3106 }
3107 return check_depths;
3108}
3109
3110
3111uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3112 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3113 uint32_t check_depths = 0;
3114 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3115 if (s->num_heap_slots() <= 0) continue;
3116 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3117 int depth = current_scope()->ContextChainLength(s);
3118 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3119 check_depths |= 1 << depth;
3120 if (s == variable->scope()) break;
3121 }
3122 return check_depths;
3123}
3124
3125
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003126Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3127 DCHECK(environment()->stack_height() >= arity);
3128 Node** all = info()->zone()->NewArray<Node*>(arity);
3129 for (int i = arity - 1; i >= 0; --i) {
3130 all[i] = environment()->Pop();
3131 }
3132 Node* value = NewNode(op, arity, all);
3133 return value;
3134}
3135
3136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003137Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3138 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003139
3140 // Allocate a new local context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003141 Node* local_context = scope->is_script_scope()
3142 ? BuildLocalScriptContext(scope)
3143 : BuildLocalFunctionContext(scope);
3144
3145 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3146 Node* receiver = environment()->RawParameterLookup(0);
3147 // Context variable (at bottom of the context chain).
3148 Variable* variable = scope->receiver();
3149 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3150 const Operator* op = javascript()->StoreContext(0, variable->index());
3151 NewNode(op, local_context, receiver);
3152 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003153
3154 // Copy parameters into context if necessary.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003155 int num_parameters = scope->num_parameters();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003156 for (int i = 0; i < num_parameters; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003157 Variable* variable = scope->parameter(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003158 if (!variable->IsContextSlot()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003159 Node* parameter = environment()->RawParameterLookup(i + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003160 // Context variable (at bottom of the context chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003161 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003162 const Operator* op = javascript()->StoreContext(0, variable->index());
3163 NewNode(op, local_context, parameter);
3164 }
3165
3166 return local_context;
3167}
3168
3169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003170Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
3171 DCHECK(scope->is_function_scope());
3172
3173 // Allocate a new local context.
3174 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3175 const Operator* op = javascript()->CreateFunctionContext(slot_count);
3176 Node* local_context = NewNode(op, GetFunctionClosure());
3177
3178 return local_context;
3179}
3180
3181
3182Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3183 DCHECK(scope->is_script_scope());
3184
3185 // Allocate a new local context.
3186 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3187 const Operator* op = javascript()->CreateScriptContext(scope_info);
3188 Node* local_context = NewNode(op, GetFunctionClosure());
3189 PrepareFrameState(local_context, BailoutId::ScriptContext(),
3190 OutputFrameStateCombine::Push());
3191
3192 return local_context;
3193}
3194
3195
3196Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3197 DCHECK(scope->is_block_scope());
3198
3199 // Allocate a new local context.
3200 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3201 const Operator* op = javascript()->CreateBlockContext(scope_info);
3202 Node* local_context = NewNode(op, GetFunctionClosureForContext());
3203
3204 return local_context;
3205}
3206
3207
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003208Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003209 if (arguments == nullptr) return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003210
3211 // Allocate and initialize a new arguments object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003212 CreateArgumentsParameters::Type type =
3213 is_strict(language_mode()) || !info()->has_simple_parameters()
3214 ? CreateArgumentsParameters::kUnmappedArguments
3215 : CreateArgumentsParameters::kMappedArguments;
3216 const Operator* op = javascript()->CreateArguments(type, 0);
3217 Node* object = NewNode(op, GetFunctionClosure());
3218 PrepareFrameState(object, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003220 // Assign the object to the {arguments} variable. This should never lazy
3221 // deopt, so it is fine to send invalid bailout id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003222 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003223 FrameStateBeforeAndAfter states(this, BailoutId::None());
3224 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3225 BailoutId::None(), states);
3226 return object;
3227}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003229
3230Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3231 if (rest == nullptr) return nullptr;
3232
3233 // Allocate and initialize a new arguments object.
3234 CreateArgumentsParameters::Type type = CreateArgumentsParameters::kRestArray;
3235 const Operator* op = javascript()->CreateArguments(type, index);
3236 Node* object = NewNode(op, GetFunctionClosure());
3237 PrepareFrameState(object, BailoutId::None());
3238
3239 // Assign the object to the {rest} variable. This should never lazy
3240 // deopt, so it is fine to send invalid bailout id.
3241 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3242 FrameStateBeforeAndAfter states(this, BailoutId::None());
3243 BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3244 BailoutId::None(), states);
3245 return object;
3246}
3247
3248
3249Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3250 if (this_function_var == nullptr) return nullptr;
3251
3252 // Retrieve the closure we were called with.
3253 Node* this_function = GetFunctionClosure();
3254
3255 // Assign the object to the {.this_function} variable. This should never lazy
3256 // deopt, so it is fine to send invalid bailout id.
3257 FrameStateBeforeAndAfter states(this, BailoutId::None());
3258 BuildVariableAssignment(this_function_var, this_function, Token::INIT,
3259 VectorSlotPair(), BailoutId::None(), states);
3260 return this_function;
3261}
3262
3263
3264Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3265 if (new_target_var == nullptr) return nullptr;
3266
3267 // Retrieve the new target we were called with.
3268 Node* object = GetNewTarget();
3269
3270 // Assign the object to the {new.target} variable. This should never lazy
3271 // deopt, so it is fine to send invalid bailout id.
3272 FrameStateBeforeAndAfter states(this, BailoutId::None());
3273 BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
3274 BailoutId::None(), states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003275 return object;
3276}
3277
3278
3279Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
3280 Node* not_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003281 Node* the_hole = jsgraph()->TheHoleConstant();
3282 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3283 return NewNode(
3284 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
3285 check, for_hole, not_hole);
3286}
3287
3288
3289Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3290 Node* not_hole,
3291 BailoutId bailout_id) {
3292 IfBuilder hole_check(this);
3293 Node* the_hole = jsgraph()->TheHoleConstant();
3294 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3295 hole_check.If(check);
3296 hole_check.Then();
3297 Node* error = BuildThrowReferenceError(variable, bailout_id);
3298 environment()->Push(error);
3299 hole_check.Else();
3300 environment()->Push(not_hole);
3301 hole_check.End();
3302 return environment()->Pop();
3303}
3304
3305
3306Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3307 Node* for_hole,
3308 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003309 IfBuilder hole_check(this);
3310 Node* the_hole = jsgraph()->TheHoleConstant();
3311 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3312 hole_check.If(check);
3313 hole_check.Then();
3314 environment()->Push(for_hole);
3315 hole_check.Else();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003316 Node* error = BuildThrowReferenceError(variable, bailout_id);
3317 environment()->Push(error);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003318 hole_check.End();
3319 return environment()->Pop();
3320}
3321
3322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003323Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3324 BailoutId bailout_id) {
3325 IfBuilder prototype_check(this);
3326 Node* prototype_string =
3327 jsgraph()->Constant(isolate()->factory()->prototype_string());
3328 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
3329 prototype_check.If(check);
3330 prototype_check.Then();
3331 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3332 environment()->Push(error);
3333 prototype_check.Else();
3334 environment()->Push(name);
3335 prototype_check.End();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003336 return environment()->Pop();
3337}
3338
3339
3340Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3341 BailoutId bailout_id,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003342 FrameStateBeforeAndAfter& states,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003343 const VectorSlotPair& feedback,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003344 OutputFrameStateCombine combine,
3345 TypeofMode typeof_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003346 Node* the_hole = jsgraph()->TheHoleConstant();
3347 VariableMode mode = variable->mode();
3348 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003349 case VariableLocation::GLOBAL:
3350 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003352 Handle<Name> name = variable->name();
3353 if (Node* node = TryLoadGlobalConstant(name)) return node;
3354 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
3355 states.AddToNode(value, bailout_id, combine);
3356 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003357 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003358 case VariableLocation::PARAMETER:
3359 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003360 // Local var, const, or let variable.
3361 Node* value = environment()->Lookup(variable);
3362 if (mode == CONST_LEGACY) {
3363 // Perform check for uninitialized legacy const variables.
3364 if (value->op() == the_hole->op()) {
3365 value = jsgraph()->UndefinedConstant();
3366 } else if (value->opcode() == IrOpcode::kPhi) {
3367 Node* undefined = jsgraph()->UndefinedConstant();
3368 value = BuildHoleCheckSilent(value, undefined, value);
3369 }
3370 } else if (mode == LET || mode == CONST) {
3371 // Perform check for uninitialized let/const variables.
3372 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003373 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003374 } else if (value->opcode() == IrOpcode::kPhi) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003375 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003376 }
3377 }
3378 return value;
3379 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003380 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003381 // Context variable (potentially up the context chain).
3382 int depth = current_scope()->ContextChainLength(variable->scope());
3383 bool immutable = variable->maybe_assigned() == kNotAssigned;
3384 const Operator* op =
3385 javascript()->LoadContext(depth, variable->index(), immutable);
3386 Node* value = NewNode(op, current_context());
3387 // TODO(titzer): initialization checks are redundant for already
3388 // initialized immutable context loads, but only specialization knows.
3389 // Maybe specializer should be a parameter to the graph builder?
3390 if (mode == CONST_LEGACY) {
3391 // Perform check for uninitialized legacy const variables.
3392 Node* undefined = jsgraph()->UndefinedConstant();
3393 value = BuildHoleCheckSilent(value, undefined, value);
3394 } else if (mode == LET || mode == CONST) {
3395 // Perform check for uninitialized let/const variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003396 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003397 }
3398 return value;
3399 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003400 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003401 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003402 Handle<String> name = variable->name();
3403 if (Node* node =
3404 TryLoadDynamicVariable(variable, name, bailout_id, states,
3405 feedback, combine, typeof_mode)) {
3406 return node;
3407 }
3408 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3409 Node* value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3410 states.AddToNode(value, bailout_id, combine);
3411 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003412 }
3413 }
3414 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003415 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003416}
3417
3418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003419Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3420 BailoutId bailout_id,
3421 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003422 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003423 case VariableLocation::GLOBAL:
3424 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003425 // Global var, const, or let variable.
3426 Node* global = BuildLoadGlobalObject();
3427 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003428 const Operator* op = javascript()->DeleteProperty(language_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003429 Node* result = NewNode(op, global, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003430 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003431 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003432 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003433 case VariableLocation::PARAMETER:
3434 case VariableLocation::LOCAL:
3435 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003436 // Local var, const, or let variable or context variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003437 return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3438 }
3439 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003440 // Dynamic lookup of context variable (anywhere in the chain).
3441 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003442 const Operator* op =
3443 javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
3444 Node* result = NewNode(op, current_context(), name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003445 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003446 return result;
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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003454Node* AstGraphBuilder::BuildVariableAssignment(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003455 Variable* variable, Node* value, Token::Value op,
3456 const VectorSlotPair& feedback, BailoutId bailout_id,
3457 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003458 Node* the_hole = jsgraph()->TheHoleConstant();
3459 VariableMode mode = variable->mode();
3460 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003461 case VariableLocation::GLOBAL:
3462 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003463 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003464 Handle<Name> name = variable->name();
3465 Node* store = BuildGlobalStore(name, value, feedback);
3466 states.AddToNode(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003467 return store;
3468 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003469 case VariableLocation::PARAMETER:
3470 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003471 // Local var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003472 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003473 // Perform an initialization check for legacy const variables.
3474 Node* current = environment()->Lookup(variable);
3475 if (current->op() != the_hole->op()) {
3476 value = BuildHoleCheckSilent(current, value, current);
3477 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003478 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3479 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003480 // - exception in strict mode.
3481 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003482 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003483 return BuildThrowConstAssignError(bailout_id);
3484 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003485 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003486 } else if (mode == LET && op == Token::INIT) {
3487 // No initialization check needed because scoping guarantees it. Note
3488 // that we still perform a lookup to keep the variable live, because
3489 // baseline code might contain debug code that inspects the variable.
3490 Node* current = environment()->Lookup(variable);
3491 CHECK_NOT_NULL(current);
3492 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003493 // Perform an initialization check for let declared variables.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003494 Node* current = environment()->Lookup(variable);
3495 if (current->op() == the_hole->op()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003496 return BuildThrowReferenceError(variable, bailout_id);
3497 } else if (current->opcode() == IrOpcode::kPhi) {
3498 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003499 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003500 } else if (mode == CONST && op == Token::INIT) {
3501 // Perform an initialization check for const {this} variables.
3502 // Note that the {this} variable is the only const variable being able
3503 // to trigger bind operations outside the TDZ, via {super} calls.
3504 Node* current = environment()->Lookup(variable);
3505 if (current->op() != the_hole->op() && variable->is_this()) {
3506 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3507 }
3508 } else if (mode == CONST && op != Token::INIT) {
3509 // Assignment to const is exception in all modes.
3510 Node* current = environment()->Lookup(variable);
3511 if (current->op() == the_hole->op()) {
3512 return BuildThrowReferenceError(variable, bailout_id);
3513 } else if (current->opcode() == IrOpcode::kPhi) {
3514 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3515 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003516 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003517 }
3518 environment()->Bind(variable, value);
3519 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003520 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003521 // Context variable (potentially up the context chain).
3522 int depth = current_scope()->ContextChainLength(variable->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003523 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003524 // Perform an initialization check for legacy const variables.
3525 const Operator* op =
3526 javascript()->LoadContext(depth, variable->index(), false);
3527 Node* current = NewNode(op, current_context());
3528 value = BuildHoleCheckSilent(current, value, current);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003529 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3530 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003531 // - exception in strict mode.
3532 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003533 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003534 return BuildThrowConstAssignError(bailout_id);
3535 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003536 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003537 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003538 // Perform an initialization check for let declared variables.
3539 const Operator* op =
3540 javascript()->LoadContext(depth, variable->index(), false);
3541 Node* current = NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003542 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3543 } else if (mode == CONST && op == Token::INIT) {
3544 // Perform an initialization check for const {this} variables.
3545 // Note that the {this} variable is the only const variable being able
3546 // to trigger bind operations outside the TDZ, via {super} calls.
3547 if (variable->is_this()) {
3548 const Operator* op =
3549 javascript()->LoadContext(depth, variable->index(), false);
3550 Node* current = NewNode(op, current_context());
3551 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3552 }
3553 } else if (mode == CONST && op != Token::INIT) {
3554 // Assignment to const is exception in all modes.
3555 const Operator* op =
3556 javascript()->LoadContext(depth, variable->index(), false);
3557 Node* current = NewNode(op, current_context());
3558 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003559 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003560 }
3561 const Operator* op = javascript()->StoreContext(depth, variable->index());
3562 return NewNode(op, current_context(), value);
3563 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003564 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003565 // Dynamic lookup of context variable (anywhere in the chain).
3566 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003567 Node* language = jsgraph()->Constant(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003568 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
3569 // initializations of const declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003570 const Operator* op =
3571 javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003572 Node* store = NewNode(op, value, current_context(), name, language);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003573 PrepareFrameState(store, bailout_id, combine);
3574 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003575 }
3576 }
3577 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003578 return nullptr;
3579}
3580
3581
3582Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3583 const VectorSlotPair& feedback) {
3584 const Operator* op = javascript()->LoadProperty(language_mode(), feedback);
3585 Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
3586 return node;
3587}
3588
3589
3590Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3591 const VectorSlotPair& feedback) {
3592 const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
3593 Node* node = NewNode(op, object, BuildLoadFeedbackVector());
3594 return node;
3595}
3596
3597
3598Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3599 const VectorSlotPair& feedback) {
3600 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
3601 Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
3602 return node;
3603}
3604
3605
3606Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3607 Node* value,
3608 const VectorSlotPair& feedback) {
3609 const Operator* op =
3610 javascript()->StoreNamed(language_mode(), name, feedback);
3611 Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
3612 return node;
3613}
3614
3615
3616Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3617 Handle<Name> name,
3618 const VectorSlotPair& feedback) {
3619 Node* name_node = jsgraph()->Constant(name);
3620 Node* language = jsgraph()->Constant(language_mode());
3621 const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 4);
3622 Node* node = NewNode(op, receiver, home_object, name_node, language);
3623 return node;
3624}
3625
3626
3627Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3628 Node* key,
3629 const VectorSlotPair& feedback) {
3630 Node* language = jsgraph()->Constant(language_mode());
3631 const Operator* op =
3632 javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
3633 Node* node = NewNode(op, receiver, home_object, key, language);
3634 return node;
3635}
3636
3637
3638Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3639 Node* key, Node* value) {
3640 Runtime::FunctionId function_id = is_strict(language_mode())
3641 ? Runtime::kStoreKeyedToSuper_Strict
3642 : Runtime::kStoreKeyedToSuper_Sloppy;
3643 const Operator* op = javascript()->CallRuntime(function_id, 4);
3644 Node* node = NewNode(op, receiver, home_object, key, value);
3645 return node;
3646}
3647
3648
3649Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3650 Handle<Name> name, Node* value) {
3651 Node* name_node = jsgraph()->Constant(name);
3652 Runtime::FunctionId function_id = is_strict(language_mode())
3653 ? Runtime::kStoreToSuper_Strict
3654 : Runtime::kStoreToSuper_Sloppy;
3655 const Operator* op = javascript()->CallRuntime(function_id, 4);
3656 Node* node = NewNode(op, receiver, home_object, name_node, value);
3657 return node;
3658}
3659
3660
3661Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3662 const VectorSlotPair& feedback,
3663 TypeofMode typeof_mode) {
3664 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
3665 Node* node = NewNode(op, BuildLoadFeedbackVector());
3666 return node;
3667}
3668
3669
3670Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3671 const VectorSlotPair& feedback) {
3672 const Operator* op =
3673 javascript()->StoreGlobal(language_mode(), name, feedback);
3674 Node* node = NewNode(op, value, BuildLoadFeedbackVector());
3675 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003676}
3677
3678
3679Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003680 return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object,
3681 jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003682}
3683
3684
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003685Node* AstGraphBuilder::BuildLoadImmutableObjectField(Node* object, int offset) {
3686 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()),
3687 object,
3688 jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
3689 graph()->start(), graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003690}
3691
3692
3693Node* AstGraphBuilder::BuildLoadGlobalObject() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003694 return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003695}
3696
3697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003698Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3699 const Operator* op =
3700 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3701 Node* native_context = NewNode(op, current_context());
3702 return NewNode(javascript()->LoadContext(0, index, true), native_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003703}
3704
3705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003706Node* AstGraphBuilder::BuildLoadFeedbackVector() {
3707 if (!feedback_vector_.is_set()) {
3708 Node* closure = GetFunctionClosure();
3709 Node* shared = BuildLoadImmutableObjectField(
3710 closure, JSFunction::kSharedFunctionInfoOffset);
3711 Node* vector = BuildLoadImmutableObjectField(
3712 shared, SharedFunctionInfo::kFeedbackVectorOffset);
3713 feedback_vector_.set(vector);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003714 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003715 return feedback_vector_.get();
3716}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003718
3719Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3720 if (Node* node = TryFastToBoolean(input)) return node;
3721 ToBooleanHints hints;
3722 if (!type_hint_analysis_ ||
3723 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3724 hints = ToBooleanHint::kAny;
3725 }
3726 return NewNode(javascript()->ToBoolean(hints), input);
3727}
3728
3729
3730Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3731 if (Node* node = TryFastToName(input)) return node;
3732 Node* name = NewNode(javascript()->ToName(), input);
3733 PrepareFrameState(name, bailout_id);
3734 return name;
3735}
3736
3737
3738Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3739 Node* object = NewNode(javascript()->ToObject(), input);
3740 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3741 return object;
3742}
3743
3744
3745Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3746 ObjectLiteralProperty* property,
3747 int slot_number) {
3748 Expression* expr = property->value();
3749 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3750 Handle<Name> name = isolate()->factory()->home_object_symbol();
3751 FrameStateBeforeAndAfter states(this, BailoutId::None());
3752 VectorSlotPair feedback =
3753 CreateVectorSlotPair(property->GetSlot(slot_number));
3754 Node* store = BuildNamedStore(value, name, home_object, feedback);
3755 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3756 return store;
3757}
3758
3759
3760Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
3761 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
3762 Node* call = NewNode(op, exception);
3763 PrepareFrameState(call, bailout_id);
3764 Node* control = NewNode(common()->Throw(), call);
3765 UpdateControlDependencyToLeaveFunction(control);
3766 return call;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003767}
3768
3769
3770Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3771 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003772 Node* variable_name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003773 const Operator* op =
3774 javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
3775 Node* call = NewNode(op, variable_name);
3776 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003777 Node* control = NewNode(common()->Throw(), call);
3778 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003779 return call;
3780}
3781
3782
3783Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003784 const Operator* op =
3785 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
3786 Node* call = NewNode(op);
3787 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003788 Node* control = NewNode(common()->Throw(), call);
3789 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003790 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003791}
3792
3793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003794Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3795 const Operator* op =
3796 javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError, 0);
3797 Node* call = NewNode(op);
3798 PrepareFrameState(call, bailout_id);
3799 Node* control = NewNode(common()->Throw(), call);
3800 UpdateControlDependencyToLeaveFunction(control);
3801 return call;
3802}
3803
3804
3805Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3806 const Operator* op =
3807 javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
3808 Node* call = NewNode(op);
3809 PrepareFrameState(call, bailout_id);
3810 Node* control = NewNode(common()->Throw(), call);
3811 UpdateControlDependencyToLeaveFunction(control);
3812 return call;
3813}
3814
3815
3816Node* AstGraphBuilder::BuildReturn(Node* return_value) {
3817 Node* control = NewNode(common()->Return(), return_value);
3818 UpdateControlDependencyToLeaveFunction(control);
3819 return control;
3820}
3821
3822
3823Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
3824 NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), exception_value);
3825 Node* control = NewNode(common()->Throw(), exception_value);
3826 UpdateControlDependencyToLeaveFunction(control);
3827 return control;
3828}
3829
3830
3831Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3832 TypeFeedbackId feedback_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003833 const Operator* js_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003834 BinaryOperationHints hints;
3835 if (!type_hint_analysis_ ||
3836 !type_hint_analysis_->GetBinaryOperationHints(feedback_id, &hints)) {
3837 hints = BinaryOperationHints::Any();
3838 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003839 switch (op) {
3840 case Token::BIT_OR:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 js_op = javascript()->BitwiseOr(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003842 break;
3843 case Token::BIT_AND:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003844 js_op = javascript()->BitwiseAnd(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003845 break;
3846 case Token::BIT_XOR:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003847 js_op = javascript()->BitwiseXor(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003848 break;
3849 case Token::SHL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003850 js_op = javascript()->ShiftLeft(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003851 break;
3852 case Token::SAR:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003853 js_op = javascript()->ShiftRight(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003854 break;
3855 case Token::SHR:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003856 js_op = javascript()->ShiftRightLogical(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003857 break;
3858 case Token::ADD:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003859 js_op = javascript()->Add(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003860 break;
3861 case Token::SUB:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003862 js_op = javascript()->Subtract(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003863 break;
3864 case Token::MUL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003865 js_op = javascript()->Multiply(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003866 break;
3867 case Token::DIV:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003868 js_op = javascript()->Divide(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003869 break;
3870 case Token::MOD:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003871 js_op = javascript()->Modulus(language_mode(), hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003872 break;
3873 default:
3874 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003875 js_op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003876 }
3877 return NewNode(js_op, left, right);
3878}
3879
3880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003881Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3882 // Optimize global constants like "undefined", "Infinity", and "NaN".
3883 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3884 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3885 return nullptr;
3886}
3887
3888
3889Node* AstGraphBuilder::TryLoadDynamicVariable(
3890 Variable* variable, Handle<String> name, BailoutId bailout_id,
3891 FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
3892 OutputFrameStateCombine combine, TypeofMode typeof_mode) {
3893 VariableMode mode = variable->mode();
3894
3895 if (mode == DYNAMIC_GLOBAL) {
3896 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3897 if (bitset == kFullCheckRequired) return nullptr;
3898
3899 // We are using two blocks to model fast and slow cases.
3900 BlockBuilder fast_block(this);
3901 BlockBuilder slow_block(this);
3902 environment()->Push(jsgraph()->TheHoleConstant());
3903 slow_block.BeginBlock();
3904 environment()->Pop();
3905 fast_block.BeginBlock();
3906
3907 // Perform checks whether the fast mode applies, by looking for any
3908 // extension object which might shadow the optimistic declaration.
3909 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3910 if ((bitset & 1) == 0) continue;
3911 Node* load = NewNode(
3912 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3913 current_context());
3914 Node* check = NewNode(javascript()->StrictEqual(), load,
3915 jsgraph()->TheHoleConstant());
3916 fast_block.BreakUnless(check, BranchHint::kTrue);
3917 }
3918
3919 // Fast case, because variable is not shadowed. Perform global slot load.
3920 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3921 states.AddToNode(fast, bailout_id, combine);
3922 environment()->Push(fast);
3923 slow_block.Break();
3924 environment()->Pop();
3925 fast_block.EndBlock();
3926
3927 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3928 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3929 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
3930 states.AddToNode(slow, bailout_id, combine);
3931 environment()->Push(slow);
3932 slow_block.EndBlock();
3933
3934 return environment()->Pop();
3935 }
3936
3937 if (mode == DYNAMIC_LOCAL) {
3938 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3939 if (bitset == kFullCheckRequired) return nullptr;
3940
3941 // We are using two blocks to model fast and slow cases.
3942 BlockBuilder fast_block(this);
3943 BlockBuilder slow_block(this);
3944 environment()->Push(jsgraph()->TheHoleConstant());
3945 slow_block.BeginBlock();
3946 environment()->Pop();
3947 fast_block.BeginBlock();
3948
3949 // Perform checks whether the fast mode applies, by looking for any
3950 // extension object which might shadow the optimistic declaration.
3951 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3952 if ((bitset & 1) == 0) continue;
3953 Node* load = NewNode(
3954 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3955 current_context());
3956 Node* check = NewNode(javascript()->StrictEqual(), load,
3957 jsgraph()->TheHoleConstant());
3958 fast_block.BreakUnless(check, BranchHint::kTrue);
3959 }
3960
3961 // Fast case, because variable is not shadowed. Perform context slot load.
3962 Variable* local = variable->local_if_not_shadowed();
3963 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3964 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3965 typeof_mode);
3966 environment()->Push(fast);
3967 slow_block.Break();
3968 environment()->Pop();
3969 fast_block.EndBlock();
3970
3971 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3972 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
3973 Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
3974 states.AddToNode(slow, bailout_id, combine);
3975 environment()->Push(slow);
3976 slow_block.EndBlock();
3977
3978 return environment()->Pop();
3979 }
3980
3981 return nullptr;
3982}
3983
3984
3985Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3986 switch (input->opcode()) {
3987 case IrOpcode::kNumberConstant: {
3988 NumberMatcher m(input);
3989 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3990 }
3991 case IrOpcode::kHeapConstant: {
3992 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3993 return jsgraph_->BooleanConstant(object->BooleanValue());
3994 }
3995 case IrOpcode::kJSEqual:
3996 case IrOpcode::kJSNotEqual:
3997 case IrOpcode::kJSStrictEqual:
3998 case IrOpcode::kJSStrictNotEqual:
3999 case IrOpcode::kJSLessThan:
4000 case IrOpcode::kJSLessThanOrEqual:
4001 case IrOpcode::kJSGreaterThan:
4002 case IrOpcode::kJSGreaterThanOrEqual:
4003 case IrOpcode::kJSToBoolean:
4004 case IrOpcode::kJSDeleteProperty:
4005 case IrOpcode::kJSHasProperty:
4006 case IrOpcode::kJSInstanceOf:
4007 return input;
4008 default:
4009 break;
4010 }
4011 return nullptr;
4012}
4013
4014
4015Node* AstGraphBuilder::TryFastToName(Node* input) {
4016 switch (input->opcode()) {
4017 case IrOpcode::kHeapConstant: {
4018 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4019 if (object->IsName()) return input;
4020 break;
4021 }
4022 case IrOpcode::kJSToString:
4023 case IrOpcode::kJSToName:
4024 case IrOpcode::kJSTypeOf:
4025 return input;
4026 default:
4027 break;
4028 }
4029 return nullptr;
4030}
4031
4032
4033bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4034 if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4035 info()->set_osr_expr_stack_height(std::max(
4036 environment()->stack_height(), info()->osr_expr_stack_height()));
4037 return true;
4038 }
4039 return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004040}
4041
4042
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004043void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4044 OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004045 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4046 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4047
4048 DCHECK_EQ(IrOpcode::kDead,
4049 NodeProperties::GetFrameStateInput(node, 0)->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004050 NodeProperties::ReplaceFrameStateInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004051 node, 0, environment()->Checkpoint(ast_id, combine));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004052 }
4053}
4054
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004055
4056BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4057 IterationStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004058 if (loop_assignment_analysis_ == nullptr) return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004059 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004060}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004061
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004062
4063Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4064 if (size > input_buffer_size_) {
4065 size = size + kInputBufferSizeIncrement + input_buffer_size_;
4066 input_buffer_ = local_zone()->NewArray<Node*>(size);
4067 input_buffer_size_ = size;
4068 }
4069 return input_buffer_;
4070}
4071
4072
4073Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4074 Node** value_inputs, bool incomplete) {
4075 DCHECK_EQ(op->ValueInputCount(), value_input_count);
4076
4077 bool has_context = OperatorProperties::HasContextInput(op);
4078 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4079 bool has_control = op->ControlInputCount() == 1;
4080 bool has_effect = op->EffectInputCount() == 1;
4081
4082 DCHECK(op->ControlInputCount() < 2);
4083 DCHECK(op->EffectInputCount() < 2);
4084
4085 Node* result = nullptr;
4086 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4087 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4088 } else {
4089 bool inside_try_scope = try_nesting_level_ > 0;
4090 int input_count_with_deps = value_input_count;
4091 if (has_context) ++input_count_with_deps;
4092 input_count_with_deps += frame_state_count;
4093 if (has_control) ++input_count_with_deps;
4094 if (has_effect) ++input_count_with_deps;
4095 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4096 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4097 Node** current_input = buffer + value_input_count;
4098 if (has_context) {
4099 *current_input++ = current_context();
4100 }
4101 for (int i = 0; i < frame_state_count; i++) {
4102 // The frame state will be inserted later. Here we misuse
4103 // the {Dead} node as a sentinel to be later overwritten
4104 // with the real frame state.
4105 *current_input++ = jsgraph()->Dead();
4106 }
4107 if (has_effect) {
4108 *current_input++ = environment_->GetEffectDependency();
4109 }
4110 if (has_control) {
4111 *current_input++ = environment_->GetControlDependency();
4112 }
4113 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4114 if (!environment()->IsMarkedAsUnreachable()) {
4115 // Update the current control dependency for control-producing nodes.
4116 if (NodeProperties::IsControl(result)) {
4117 environment_->UpdateControlDependency(result);
4118 }
4119 // Update the current effect dependency for effect-producing nodes.
4120 if (result->op()->EffectOutputCount() > 0) {
4121 environment_->UpdateEffectDependency(result);
4122 }
4123 // Add implicit exception continuation for throwing nodes.
4124 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4125 // Conservative prediction whether caught locally.
4126 IfExceptionHint hint = try_catch_nesting_level_ > 0
4127 ? IfExceptionHint::kLocallyCaught
4128 : IfExceptionHint::kLocallyUncaught;
4129 // Copy the environment for the success continuation.
4130 Environment* success_env = environment()->CopyForConditional();
4131 const Operator* op = common()->IfException(hint);
4132 Node* effect = environment()->GetEffectDependency();
4133 Node* on_exception = graph()->NewNode(op, effect, result);
4134 environment_->UpdateControlDependency(on_exception);
4135 environment_->UpdateEffectDependency(on_exception);
4136 execution_control()->ThrowValue(on_exception);
4137 set_environment(success_env);
4138 }
4139 // Add implicit success continuation for throwing nodes.
4140 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4141 const Operator* op = common()->IfSuccess();
4142 Node* on_success = graph()->NewNode(op, result);
4143 environment_->UpdateControlDependency(on_success);
4144 }
4145 }
4146 }
4147
4148 return result;
4149}
4150
4151
4152void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4153 if (environment()->IsMarkedAsUnreachable()) return;
4154 environment()->MarkAsUnreachable();
4155 exit_controls_.push_back(exit);
4156}
4157
4158
4159void AstGraphBuilder::Environment::Merge(Environment* other) {
4160 DCHECK(values_.size() == other->values_.size());
4161 DCHECK(contexts_.size() == other->contexts_.size());
4162
4163 // Nothing to do if the other environment is dead.
4164 if (other->IsMarkedAsUnreachable()) return;
4165
4166 // Resurrect a dead environment by copying the contents of the other one and
4167 // placing a singleton merge as the new control dependency.
4168 if (this->IsMarkedAsUnreachable()) {
4169 Node* other_control = other->control_dependency_;
4170 Node* inputs[] = {other_control};
4171 control_dependency_ =
4172 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4173 effect_dependency_ = other->effect_dependency_;
4174 values_ = other->values_;
4175 contexts_ = other->contexts_;
4176 if (IsLivenessAnalysisEnabled()) {
4177 liveness_block_ =
4178 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4179 }
4180 return;
4181 }
4182
4183 // Record the merge for the local variable liveness calculation.
4184 // For loops, we are connecting a back edge into the existing block;
4185 // for merges, we create a new merged block.
4186 if (IsLivenessAnalysisEnabled()) {
4187 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4188 liveness_block_ =
4189 builder_->liveness_analyzer()->NewBlock(liveness_block());
4190 }
4191 liveness_block()->AddPredecessor(other->liveness_block());
4192 }
4193
4194 // Create a merge of the control dependencies of both environments and update
4195 // the current environment's control dependency accordingly.
4196 Node* control = builder_->MergeControl(this->GetControlDependency(),
4197 other->GetControlDependency());
4198 UpdateControlDependency(control);
4199
4200 // Create a merge of the effect dependencies of both environments and update
4201 // the current environment's effect dependency accordingly.
4202 Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4203 other->GetEffectDependency(), control);
4204 UpdateEffectDependency(effect);
4205
4206 // Introduce Phi nodes for values that have differing input at merge points,
4207 // potentially extending an existing Phi node if possible.
4208 for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4209 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4210 }
4211 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4212 contexts_[i] =
4213 builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4214 }
4215}
4216
4217
4218void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4219 bool is_osr) {
4220 int size = static_cast<int>(values()->size());
4221
4222 Node* control = builder_->NewLoop();
4223 if (assigned == nullptr) {
4224 // Assume that everything is updated in the loop.
4225 for (int i = 0; i < size; ++i) {
4226 values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4227 }
4228 } else {
4229 // Only build phis for those locals assigned in this loop.
4230 for (int i = 0; i < size; ++i) {
4231 if (i < assigned->length() && !assigned->Contains(i)) continue;
4232 Node* phi = builder_->NewPhi(1, values()->at(i), control);
4233 values()->at(i) = phi;
4234 }
4235 }
4236 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4237 UpdateEffectDependency(effect);
4238
4239 // Connect the loop to end via Terminate if it's not marked as unreachable.
4240 if (!IsMarkedAsUnreachable()) {
4241 // Connect the Loop node to end via a Terminate node.
4242 Node* terminate = builder_->graph()->NewNode(
4243 builder_->common()->Terminate(), effect, control);
4244 builder_->exit_controls_.push_back(terminate);
4245 }
4246
4247 if (builder_->info()->is_osr()) {
4248 // Introduce phis for all context values in the case of an OSR graph.
4249 for (size_t i = 0; i < contexts()->size(); ++i) {
4250 Node* context = contexts()->at(i);
4251 contexts()->at(i) = builder_->NewPhi(1, context, control);
4252 }
4253 }
4254
4255 if (is_osr) {
4256 // Merge OSR values as inputs to the phis of the loop.
4257 Graph* graph = builder_->graph();
4258 Node* osr_loop_entry = builder_->graph()->NewNode(
4259 builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4260
4261 builder_->MergeControl(control, osr_loop_entry);
4262 builder_->MergeEffect(effect, osr_loop_entry, control);
4263
4264 for (int i = 0; i < size; ++i) {
4265 Node* value = values()->at(i);
4266 Node* osr_value =
4267 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4268 values()->at(i) = builder_->MergeValue(value, osr_value, control);
4269 }
4270
4271 // Rename all the contexts in the environment.
4272 // The innermost context is the OSR value, and the outer contexts are
4273 // reconstructed by dynamically walking up the context chain.
4274 Node* osr_context = nullptr;
4275 const Operator* op =
4276 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4277 const Operator* op_inner =
4278 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4279 int last = static_cast<int>(contexts()->size() - 1);
4280 for (int i = last; i >= 0; i--) {
4281 Node* context = contexts()->at(i);
4282 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4283 : graph->NewNode(op, osr_context, osr_context,
4284 osr_loop_entry);
4285 contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4286 }
4287 }
4288}
4289
4290
4291Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4292 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4293 Node** buffer = EnsureInputBufferSize(count + 1);
4294 MemsetPointer(buffer, input, count);
4295 buffer[count] = control;
4296 return graph()->NewNode(phi_op, count + 1, buffer, true);
4297}
4298
4299
4300// TODO(mstarzinger): Revisit this once we have proper effect states.
4301Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4302 const Operator* phi_op = common()->EffectPhi(count);
4303 Node** buffer = EnsureInputBufferSize(count + 1);
4304 MemsetPointer(buffer, input, count);
4305 buffer[count] = control;
4306 return graph()->NewNode(phi_op, count + 1, buffer, true);
4307}
4308
4309
4310Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4311 int inputs = control->op()->ControlInputCount() + 1;
4312 if (control->opcode() == IrOpcode::kLoop) {
4313 // Control node for loop exists, add input.
4314 const Operator* op = common()->Loop(inputs);
4315 control->AppendInput(graph_zone(), other);
4316 NodeProperties::ChangeOp(control, op);
4317 } else if (control->opcode() == IrOpcode::kMerge) {
4318 // Control node for merge exists, add input.
4319 const Operator* op = common()->Merge(inputs);
4320 control->AppendInput(graph_zone(), other);
4321 NodeProperties::ChangeOp(control, op);
4322 } else {
4323 // Control node is a singleton, introduce a merge.
4324 const Operator* op = common()->Merge(inputs);
4325 Node* inputs[] = {control, other};
4326 control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4327 }
4328 return control;
4329}
4330
4331
4332Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4333 int inputs = control->op()->ControlInputCount();
4334 if (value->opcode() == IrOpcode::kEffectPhi &&
4335 NodeProperties::GetControlInput(value) == control) {
4336 // Phi already exists, add input.
4337 value->InsertInput(graph_zone(), inputs - 1, other);
4338 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4339 } else if (value != other) {
4340 // Phi does not exist yet, introduce one.
4341 value = NewEffectPhi(inputs, value, control);
4342 value->ReplaceInput(inputs - 1, other);
4343 }
4344 return value;
4345}
4346
4347
4348Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4349 int inputs = control->op()->ControlInputCount();
4350 if (value->opcode() == IrOpcode::kPhi &&
4351 NodeProperties::GetControlInput(value) == control) {
4352 // Phi already exists, add input.
4353 value->InsertInput(graph_zone(), inputs - 1, other);
4354 NodeProperties::ChangeOp(
4355 value, common()->Phi(MachineRepresentation::kTagged, inputs));
4356 } else if (value != other) {
4357 // Phi does not exist yet, introduce one.
4358 value = NewPhi(inputs, value, control);
4359 value->ReplaceInput(inputs - 1, other);
4360 }
4361 return value;
4362}
4363
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004364} // namespace compiler
4365} // namespace internal
4366} // namespace v8