blob: abcf828c39c269593b2842943afb65eea09b52f2 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/ast-graph-builder.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/compiler/ast-loop-assignment-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/control-builders.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/linkage.h"
12#include "src/compiler/liveness-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/machine-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/compiler/node-matchers.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015#include "src/compiler/node-properties.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/compiler/operator-properties.h"
17#include "src/compiler/state-values-utils.h"
18#include "src/compiler/type-hint-analyzer.h"
19#include "src/parsing/parser.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020
21namespace v8 {
22namespace internal {
23namespace compiler {
24
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025
26// Each expression in the AST is evaluated in a specific context. This context
27// decides how the evaluation result is passed up the visitor.
28class AstGraphBuilder::AstContext BASE_EMBEDDED {
29 public:
30 bool IsEffect() const { return kind_ == Expression::kEffect; }
31 bool IsValue() const { return kind_ == Expression::kValue; }
32 bool IsTest() const { return kind_ == Expression::kTest; }
33
34 // Determines how to combine the frame state with the value
35 // that is about to be plugged into this AstContext.
36 OutputFrameStateCombine GetStateCombine() {
37 return IsEffect() ? OutputFrameStateCombine::Ignore()
38 : OutputFrameStateCombine::Push();
39 }
40
41 // Plug a node into this expression context. Call this function in tail
42 // position in the Visit functions for expressions.
43 virtual void ProduceValue(Node* value) = 0;
44
45 // Unplugs a node from this expression context. Call this to retrieve the
46 // result of another Visit function that already plugged the context.
47 virtual Node* ConsumeValue() = 0;
48
49 // Shortcut for "context->ProduceValue(context->ConsumeValue())".
50 void ReplaceValue() { ProduceValue(ConsumeValue()); }
51
52 protected:
53 AstContext(AstGraphBuilder* owner, Expression::Context kind);
54 virtual ~AstContext();
55
56 AstGraphBuilder* owner() const { return owner_; }
57 Environment* environment() const { return owner_->environment(); }
58
59// We want to be able to assert, in a context-specific way, that the stack
60// height makes sense when the context is filled.
61#ifdef DEBUG
62 int original_height_;
63#endif
64
65 private:
66 Expression::Context kind_;
67 AstGraphBuilder* owner_;
68 AstContext* outer_;
69};
70
71
72// Context to evaluate expression for its side effects only.
73class AstGraphBuilder::AstEffectContext final : public AstContext {
74 public:
75 explicit AstEffectContext(AstGraphBuilder* owner)
76 : AstContext(owner, Expression::kEffect) {}
77 ~AstEffectContext() final;
78 void ProduceValue(Node* value) final;
79 Node* ConsumeValue() final;
80};
81
82
83// Context to evaluate expression for its value (and side effects).
84class AstGraphBuilder::AstValueContext final : public AstContext {
85 public:
86 explicit AstValueContext(AstGraphBuilder* owner)
87 : AstContext(owner, Expression::kValue) {}
88 ~AstValueContext() final;
89 void ProduceValue(Node* value) final;
90 Node* ConsumeValue() final;
91};
92
93
94// Context to evaluate expression for a condition value (and side effects).
95class AstGraphBuilder::AstTestContext final : public AstContext {
96 public:
97 AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
98 : AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
99 ~AstTestContext() final;
100 void ProduceValue(Node* value) final;
101 Node* ConsumeValue() final;
102
103 private:
104 TypeFeedbackId const feedback_id_;
105};
106
107
108// Scoped class tracking context objects created by the visitor. Represents
109// mutations of the context chain within the function body and allows to
110// change the current {scope} and {context} during visitation.
111class AstGraphBuilder::ContextScope BASE_EMBEDDED {
112 public:
113 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
114 : builder_(builder),
115 outer_(builder->execution_context()),
116 scope_(scope),
117 depth_(builder_->environment()->context_chain_length()) {
118 builder_->environment()->PushContext(context); // Push.
119 builder_->set_execution_context(this);
120 }
121
122 ~ContextScope() {
123 builder_->set_execution_context(outer_); // Pop.
124 builder_->environment()->PopContext();
125 CHECK_EQ(depth_, builder_->environment()->context_chain_length());
126 }
127
128 // Current scope during visitation.
129 Scope* scope() const { return scope_; }
130
131 private:
132 AstGraphBuilder* builder_;
133 ContextScope* outer_;
134 Scope* scope_;
135 int depth_;
136};
137
138
139// Scoped class tracking control statements entered by the visitor. There are
140// different types of statements participating in this stack to properly track
141// local as well as non-local control flow:
142// - IterationStatement : Allows proper 'break' and 'continue' behavior.
143// - BreakableStatement : Allows 'break' from block and switch statements.
144// - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges.
145// - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
146class AstGraphBuilder::ControlScope BASE_EMBEDDED {
147 public:
148 explicit ControlScope(AstGraphBuilder* builder)
149 : builder_(builder),
150 outer_(builder->execution_control()),
151 context_length_(builder->environment()->context_chain_length()),
152 stack_height_(builder->environment()->stack_height()) {
153 builder_->set_execution_control(this); // Push.
154 }
155
156 virtual ~ControlScope() {
157 builder_->set_execution_control(outer_); // Pop.
158 }
159
160 // Either 'break' or 'continue' to the target statement.
161 void BreakTo(BreakableStatement* target);
162 void ContinueTo(BreakableStatement* target);
163
164 // Either 'return' or 'throw' the given value.
165 void ReturnValue(Node* return_value);
166 void ThrowValue(Node* exception_value);
167
168 class DeferredCommands;
169
170 protected:
171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
172
173 // Performs one of the above commands on this stack of control scopes. This
174 // walks through the stack giving each scope a chance to execute or defer the
175 // given command by overriding the {Execute} method appropriately. Note that
176 // this also drops extra operands from the environment for each skipped scope.
177 void PerformCommand(Command cmd, Statement* target, Node* value);
178
179 // Interface to execute a given command in this scope. Returning {true} here
180 // indicates successful execution whereas {false} requests to skip scope.
181 virtual bool Execute(Command cmd, Statement* target, Node* value) {
182 // For function-level control.
183 switch (cmd) {
184 case CMD_THROW:
185 builder()->BuildThrow(value);
186 return true;
187 case CMD_RETURN:
188 builder()->BuildReturn(value);
189 return true;
190 case CMD_BREAK:
191 case CMD_CONTINUE:
192 break;
193 }
194 return false;
195 }
196
197 Environment* environment() { return builder_->environment(); }
198 AstGraphBuilder* builder() const { return builder_; }
199 int context_length() const { return context_length_; }
200 int stack_height() const { return stack_height_; }
201
202 private:
203 AstGraphBuilder* builder_;
204 ControlScope* outer_;
205 int context_length_;
206 int stack_height_;
207};
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209// Helper class for a try-finally control scope. It can record intercepted
210// control-flow commands that cause entry into a finally-block, and re-apply
211// them after again leaving that block. Special tokens are used to identify
212// paths going through the finally-block to dispatch after leaving the block.
213class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
214 public:
215 explicit DeferredCommands(AstGraphBuilder* owner)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 : owner_(owner),
217 deferred_(owner->local_zone()),
218 return_token_(nullptr),
219 throw_token_(nullptr) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220
221 // One recorded control-flow command.
222 struct Entry {
223 Command command; // The command type being applied on this path.
224 Statement* statement; // The target statement for the command or {nullptr}.
225 Node* token; // A token identifying this particular path.
226 };
227
228 // Records a control-flow command while entering the finally-block. This also
229 // generates a new dispatch token that identifies one particular path.
230 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231 Node* token = nullptr;
232 switch (cmd) {
233 case CMD_BREAK:
234 case CMD_CONTINUE:
235 token = NewPathToken(dispenser_.GetBreakContinueToken());
236 break;
237 case CMD_THROW:
238 if (throw_token_) return throw_token_;
239 token = NewPathToken(TokenDispenserForFinally::kThrowToken);
240 throw_token_ = token;
241 break;
242 case CMD_RETURN:
243 if (return_token_) return return_token_;
244 token = NewPathToken(TokenDispenserForFinally::kReturnToken);
245 return_token_ = token;
246 break;
247 }
248 DCHECK_NOT_NULL(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 deferred_.push_back({cmd, stmt, token});
250 return token;
251 }
252
253 // Returns the dispatch token to be used to identify the implicit fall-through
254 // path at the end of a try-block into the corresponding finally-block.
255 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
256
257 // Applies all recorded control-flow commands after the finally-block again.
258 // This generates a dynamic dispatch on the token from the entry point.
259 void ApplyDeferredCommands(Node* token, Node* value) {
260 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
261 dispatch.BeginSwitch();
262 for (size_t i = 0; i < deferred_.size(); ++i) {
263 Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
264 dispatch.BeginLabel(static_cast<int>(i), condition);
265 dispatch.EndLabel();
266 }
267 for (size_t i = 0; i < deferred_.size(); ++i) {
268 dispatch.BeginCase(static_cast<int>(i));
269 owner_->execution_control()->PerformCommand(
270 deferred_[i].command, deferred_[i].statement, value);
271 dispatch.EndCase();
272 }
273 dispatch.EndSwitch();
274 }
275
276 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100277 Node* NewPathToken(int token_id) {
278 return owner_->jsgraph()->Constant(token_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 }
280 Node* NewPathTokenForImplicitFallThrough() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 }
283 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
284 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
285 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
286 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
287 }
288
289 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 TokenDispenserForFinally dispenser_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 AstGraphBuilder* owner_;
292 ZoneVector<Entry> deferred_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 Node* return_token_;
294 Node* throw_token_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295};
296
297
298// Control scope implementation for a BreakableStatement.
299class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
300 public:
301 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
302 ControlBuilder* control)
303 : ControlScope(owner), target_(target), control_(control) {}
304
305 protected:
306 bool Execute(Command cmd, Statement* target, Node* value) override {
307 if (target != target_) return false; // We are not the command target.
308 switch (cmd) {
309 case CMD_BREAK:
310 control_->Break();
311 return true;
312 case CMD_CONTINUE:
313 case CMD_THROW:
314 case CMD_RETURN:
315 break;
316 }
317 return false;
318 }
319
320 private:
321 BreakableStatement* target_;
322 ControlBuilder* control_;
323};
324
325
326// Control scope implementation for an IterationStatement.
327class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
328 public:
329 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
330 LoopBuilder* control)
331 : ControlScope(owner), target_(target), control_(control) {}
332
333 protected:
334 bool Execute(Command cmd, Statement* target, Node* value) override {
335 if (target != target_) return false; // We are not the command target.
336 switch (cmd) {
337 case CMD_BREAK:
338 control_->Break();
339 return true;
340 case CMD_CONTINUE:
341 control_->Continue();
342 return true;
343 case CMD_THROW:
344 case CMD_RETURN:
345 break;
346 }
347 return false;
348 }
349
350 private:
351 BreakableStatement* target_;
352 LoopBuilder* control_;
353};
354
355
356// Control scope implementation for a TryCatchStatement.
357class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
358 public:
359 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
360 : ControlScope(owner), control_(control) {
361 builder()->try_nesting_level_++; // Increment nesting.
362 builder()->try_catch_nesting_level_++;
363 }
364 ~ControlScopeForCatch() {
365 builder()->try_nesting_level_--; // Decrement nesting.
366 builder()->try_catch_nesting_level_--;
367 }
368
369 protected:
370 bool Execute(Command cmd, Statement* target, Node* value) override {
371 switch (cmd) {
372 case CMD_THROW:
373 control_->Throw(value);
374 return true;
375 case CMD_BREAK:
376 case CMD_CONTINUE:
377 case CMD_RETURN:
378 break;
379 }
380 return false;
381 }
382
383 private:
384 TryCatchBuilder* control_;
385};
386
387
388// Control scope implementation for a TryFinallyStatement.
389class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
390 public:
391 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
392 TryFinallyBuilder* control)
393 : ControlScope(owner), commands_(commands), control_(control) {
394 builder()->try_nesting_level_++; // Increment nesting.
395 }
396 ~ControlScopeForFinally() {
397 builder()->try_nesting_level_--; // Decrement nesting.
398 }
399
400 protected:
401 bool Execute(Command cmd, Statement* target, Node* value) override {
402 Node* token = commands_->RecordCommand(cmd, target, value);
403 control_->LeaveTry(token, value);
404 return true;
405 }
406
407 private:
408 DeferredCommands* commands_;
409 TryFinallyBuilder* control_;
410};
411
412
413// Helper for generating before and after frame states.
414class AstGraphBuilder::FrameStateBeforeAndAfter {
415 public:
416 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before)
417 : builder_(builder), frame_state_before_(nullptr) {
418 frame_state_before_ = id_before == BailoutId::None()
419 ? builder_->jsgraph()->EmptyFrameState()
420 : builder_->environment()->Checkpoint(id_before);
421 }
422
423 void AddToNode(
424 Node* node, BailoutId id_after,
425 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) {
426 int count = OperatorProperties::GetFrameStateInputCount(node->op());
427 DCHECK_LE(count, 2);
428
429 if (count >= 1) {
430 // Add the frame state for after the operation.
431 DCHECK_EQ(IrOpcode::kDead,
432 NodeProperties::GetFrameStateInput(node, 0)->opcode());
433
Ben Murdoch097c5b22016-05-18 11:27:45 +0100434 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 Node* frame_state_after =
437 id_after == BailoutId::None()
438 ? builder_->jsgraph()->EmptyFrameState()
Ben Murdoch097c5b22016-05-18 11:27:45 +0100439 : builder_->environment()->Checkpoint(id_after, combine,
440 node_has_exception);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441
442 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
443 }
444
445 if (count >= 2) {
446 // Add the frame state for before the operation.
447 DCHECK_EQ(IrOpcode::kDead,
448 NodeProperties::GetFrameStateInput(node, 1)->opcode());
449 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
450 }
451 }
452
453 private:
454 AstGraphBuilder* builder_;
455 Node* frame_state_before_;
456};
457
458
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
461 TypeHintAnalysis* type_hint_analysis)
462 : isolate_(info->isolate()),
463 local_zone_(local_zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 info_(info),
465 jsgraph_(jsgraph),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 environment_(nullptr),
467 ast_context_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 globals_(0, local_zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 execution_control_(nullptr),
470 execution_context_(nullptr),
471 try_catch_nesting_level_(0),
472 try_nesting_level_(0),
473 input_buffer_size_(0),
474 input_buffer_(nullptr),
475 exit_controls_(local_zone),
476 loop_assignment_analysis_(loop),
477 type_hint_analysis_(type_hint_analysis),
478 state_values_cache_(jsgraph),
479 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
480 local_zone),
481 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
482 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100483 info->scope()->num_stack_slots(), info->shared_info())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 InitializeAstVisitor(info->isolate());
485}
486
487
488Node* AstGraphBuilder::GetFunctionClosureForContext() {
489 Scope* closure_scope = current_scope()->ClosureScope();
490 if (closure_scope->is_script_scope() ||
491 closure_scope->is_module_scope()) {
492 // Contexts nested in the native context have a canonical empty function as
493 // their closure, not the anonymous closure containing the global code.
494 return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
495 } else {
496 DCHECK(closure_scope->is_function_scope());
497 return GetFunctionClosure();
498 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499}
500
501
502Node* AstGraphBuilder::GetFunctionClosure() {
503 if (!function_closure_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 int index = Linkage::kJSCallClosureParamIndex;
505 const Operator* op = common()->Parameter(index, "%closure");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 Node* node = NewNode(op, graph()->start());
507 function_closure_.set(node);
508 }
509 return function_closure_.get();
510}
511
512
513Node* AstGraphBuilder::GetFunctionContext() {
514 if (!function_context_.is_set()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 int params = info()->num_parameters_including_this();
516 int index = Linkage::GetJSCallContextParamIndex(params);
517 const Operator* op = common()->Parameter(index, "%context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 Node* node = NewNode(op, graph()->start());
519 function_context_.set(node);
520 }
521 return function_context_.get();
522}
523
524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525Node* AstGraphBuilder::GetNewTarget() {
526 if (!new_target_.is_set()) {
527 int params = info()->num_parameters_including_this();
528 int index = Linkage::GetJSCallNewTargetParamIndex(params);
529 const Operator* op = common()->Parameter(index, "%new.target");
530 Node* node = NewNode(op, graph()->start());
531 new_target_.set(node);
532 }
533 return new_target_.get();
534}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536
537bool AstGraphBuilder::CreateGraph(bool stack_check) {
538 Scope* scope = info()->scope();
539 DCHECK_NOT_NULL(graph());
540
541 // Set up the basic structure of the graph. Outputs for {Start} are the formal
542 // parameters (including the receiver) plus new target, number of arguments,
543 // context and closure.
544 int actual_parameter_count = info()->num_parameters_including_this() + 4;
545 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546
547 // Initialize the top-level environment.
548 Environment env(this, scope, graph()->start());
549 set_environment(&env);
550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551 if (info()->is_osr()) {
552 // Use OSR normal entry as the start of the top-level environment.
553 // It will be replaced with {Dead} after typing and optimizations.
554 NewNode(common()->OsrNormalEntry());
555 }
556
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400557 // Initialize the incoming context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 ContextScope incoming(this, scope, GetFunctionContext());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 // Initialize control scope.
561 ControlScope control(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
564 // not {the_hole}, because for derived classes {this} has a TDZ and the
565 // JSConstructStubForDerived magically passes {the_hole} as a receiver.
566 if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
567 env.RawParameterBind(0, jsgraph()->TheHoleConstant());
568 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 // Build local context only if there are context allocated variables.
571 if (info()->num_heap_slots() > 0) {
572 // Push a new inner context scope for the current activation.
573 Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
574 ContextScope top_context(this, scope, inner_context);
575 CreateGraphBody(stack_check);
576 } else {
577 // Simply use the outer function context in building the graph.
578 CreateGraphBody(stack_check);
579 }
580
581 // Finish the basic structure of the graph.
582 DCHECK_NE(0u, exit_controls_.size());
583 int const input_count = static_cast<int>(exit_controls_.size());
584 Node** const inputs = &exit_controls_.front();
585 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
586 graph()->SetEnd(end);
587
588 // Compute local variable liveness information and use it to relax
589 // frame states.
590 ClearNonLiveSlotsInFrameStates();
591
592 // Failures indicated by stack overflow.
593 return !HasStackOverflow();
594}
595
596
597void AstGraphBuilder::CreateGraphBody(bool stack_check) {
598 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599
600 // Build the arguments object if it is used.
601 BuildArgumentsObject(scope->arguments());
602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 // Build rest arguments array if it is used.
604 int rest_index;
605 Variable* rest_parameter = scope->rest_parameter(&rest_index);
606 BuildRestArgumentsArray(rest_parameter, rest_index);
607
608 // Build assignment to {.this_function} variable if it is used.
609 BuildThisFunctionVariable(scope->this_function_var());
610
611 // Build assignment to {new.target} variable if it is used.
612 BuildNewTargetVariable(scope->new_target_var());
613
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 // Emit tracing call if requested to do so.
615 if (FLAG_trace) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100616 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 }
618
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619 // Visit illegal re-declaration and bail out if it exists.
620 if (scope->HasIllegalRedeclaration()) {
621 VisitForEffect(scope->GetIllegalRedeclaration());
622 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 }
624
625 // Visit declarations within the function scope.
626 VisitDeclarations(scope->declarations());
627
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400628 // Build a stack-check before the body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 if (stack_check) {
630 Node* node = NewNode(javascript()->StackCheck());
631 PrepareFrameState(node, BailoutId::FunctionEntry());
632 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633
634 // Visit statements in the function body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 VisitStatements(info()->literal()->body());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 // Return 'undefined' in case we can fall off the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 BuildReturn(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639}
640
641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
643 if (!FLAG_analyze_environment_liveness ||
644 !info()->is_deoptimization_enabled()) {
645 return;
646 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 NonLiveFrameStateSlotReplacer replacer(
649 &state_values_cache_, jsgraph()->UndefinedConstant(),
650 liveness_analyzer()->local_count(), local_zone());
651 Variable* arguments = info()->scope()->arguments();
652 if (arguments != nullptr && arguments->IsStackAllocated()) {
653 replacer.MarkPermanentlyLive(arguments->index());
654 }
655 liveness_analyzer()->Run(&replacer);
656 if (FLAG_trace_environment_liveness) {
657 OFStream os(stdout);
658 liveness_analyzer()->Print(os);
659 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660}
661
662
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663// Gets the bailout id just before reading a variable proxy, but only for
664// unallocated variables.
665static BailoutId BeforeId(VariableProxy* proxy) {
666 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
667 : BailoutId::None();
668}
669
670
671static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
672#if DEBUG
673 const AstRawString* name = scope->parameter(index)->raw_name();
674 if (name && name->length() > 0) {
675 char* data = zone->NewArray<char>(name->length() + 1);
676 data[name->length()] = 0;
677 memcpy(data, name->raw_data(), name->length());
678 return data;
679 }
680#endif
681 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682}
683
684
685AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
686 Scope* scope,
687 Node* control_dependency)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000688 : builder_(builder),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 parameters_count_(scope->num_parameters() + 1),
690 locals_count_(scope->num_stack_slots()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 liveness_block_(IsLivenessAnalysisEnabled()
692 ? builder_->liveness_analyzer()->NewBlock()
693 : nullptr),
694 values_(builder_->local_zone()),
695 contexts_(builder_->local_zone()),
696 control_dependency_(control_dependency),
697 effect_dependency_(control_dependency),
698 parameters_node_(nullptr),
699 locals_node_(nullptr),
700 stack_node_(nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
702
703 // Bind the receiver variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 int param_num = 0;
705 if (builder->info()->is_this_defined()) {
706 const Operator* op = common()->Parameter(param_num++, "%this");
707 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
708 values()->push_back(receiver);
709 } else {
710 values()->push_back(builder->jsgraph()->UndefinedConstant());
711 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712
713 // Bind all parameter variables. The parameter indices are shifted by 1
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 // (receiver is variable index -1 but {Parameter} node index 0 and located at
715 // index 0 in the environment).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 for (int i = 0; i < scope->num_parameters(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
718 const Operator* op = common()->Parameter(param_num++, debug_name);
719 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 values()->push_back(parameter);
721 }
722
723 // Bind all local variables to undefined.
724 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
725 values()->insert(values()->end(), locals_count(), undefined_constant);
726}
727
728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
730 LivenessAnalyzerBlock* liveness_block)
731 : builder_(copy->builder_),
732 parameters_count_(copy->parameters_count_),
733 locals_count_(copy->locals_count_),
734 liveness_block_(liveness_block),
735 values_(copy->zone()),
736 contexts_(copy->zone()),
737 control_dependency_(copy->control_dependency_),
738 effect_dependency_(copy->effect_dependency_),
739 parameters_node_(copy->parameters_node_),
740 locals_node_(copy->locals_node_),
741 stack_node_(copy->stack_node_) {
742 const size_t kStackEstimate = 7; // optimum from experimentation!
743 values_.reserve(copy->values_.size() + kStackEstimate);
744 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
745 contexts_.reserve(copy->contexts_.size());
746 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
747 copy->contexts_.end());
748}
749
750
751void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
752 DCHECK(variable->IsStackAllocated());
753 if (variable->IsParameter()) {
754 // The parameter indices are shifted by 1 (receiver is variable
755 // index -1 but located at index 0 in the environment).
756 values()->at(variable->index() + 1) = node;
757 } else {
758 DCHECK(variable->IsStackLocal());
759 values()->at(variable->index() + parameters_count_) = node;
760 DCHECK(IsLivenessBlockConsistent());
761 if (liveness_block() != nullptr) {
762 liveness_block()->Bind(variable->index());
763 }
764 }
765}
766
767
768Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
769 DCHECK(variable->IsStackAllocated());
770 if (variable->IsParameter()) {
771 // The parameter indices are shifted by 1 (receiver is variable
772 // index -1 but located at index 0 in the environment).
773 return values()->at(variable->index() + 1);
774 } else {
775 DCHECK(variable->IsStackLocal());
776 DCHECK(IsLivenessBlockConsistent());
777 if (liveness_block() != nullptr) {
778 liveness_block()->Lookup(variable->index());
779 }
780 return values()->at(variable->index() + parameters_count_);
781 }
782}
783
784
785void AstGraphBuilder::Environment::MarkAllLocalsLive() {
786 DCHECK(IsLivenessBlockConsistent());
787 if (liveness_block() != nullptr) {
788 for (int i = 0; i < locals_count_; i++) {
789 liveness_block()->Lookup(i);
790 }
791 }
792}
793
794
795void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
796 DCHECK_LT(index, parameters_count());
797 values()->at(index) = node;
798}
799
800
801Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
802 DCHECK_LT(index, parameters_count());
803 return values()->at(index);
804}
805
806
807AstGraphBuilder::Environment*
808AstGraphBuilder::Environment::CopyForConditional() {
809 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
810 if (liveness_block() != nullptr) {
811 copy_liveness_block =
812 builder_->liveness_analyzer()->NewBlock(liveness_block());
813 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
814 }
815 return new (zone()) Environment(this, copy_liveness_block);
816}
817
818
819AstGraphBuilder::Environment*
820AstGraphBuilder::Environment::CopyAsUnreachable() {
821 Environment* env = new (zone()) Environment(this, nullptr);
822 env->MarkAsUnreachable();
823 return env;
824}
825
826
827AstGraphBuilder::Environment*
828AstGraphBuilder::Environment::CopyAndShareLiveness() {
829 if (liveness_block() != nullptr) {
830 // Finish the current liveness block before copying.
831 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
832 }
833 Environment* env = new (zone()) Environment(this, liveness_block());
834 return env;
835}
836
837
838AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
839 BitVector* assigned, bool is_osr) {
840 PrepareForLoop(assigned, is_osr);
841 return CopyAndShareLiveness();
842}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843
844
845void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
846 int offset, int count) {
847 bool should_update = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
849 if (*state_values == nullptr || (*state_values)->InputCount() != count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 should_update = true;
851 } else {
852 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
853 for (int i = 0; i < count; i++) {
854 if ((*state_values)->InputAt(i) != env_values[i]) {
855 should_update = true;
856 break;
857 }
858 }
859 }
860 if (should_update) {
861 const Operator* op = common()->StateValues(count);
862 (*state_values) = graph()->NewNode(op, count, env_values);
863 }
864}
865
866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
868 Node** state_values, int offset, int count) {
869 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
870 *state_values = builder_->state_values_cache_.GetNodeForValues(
871 env_values, static_cast<size_t>(count));
872}
873
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
875 OutputFrameStateCombine combine,
876 bool owner_has_exception) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 if (!builder()->info()->is_deoptimization_enabled()) {
878 return builder()->jsgraph()->EmptyFrameState();
879 }
880
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 UpdateStateValues(&parameters_node_, 0, parameters_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
884 stack_height());
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 const Operator* op = common()->FrameState(
887 ast_id, combine, builder()->frame_state_function_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
890 stack_node_, builder()->current_context(),
891 builder()->GetFunctionClosure(),
892 builder()->graph()->start());
893
894 DCHECK(IsLivenessBlockConsistent());
895 if (liveness_block() != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100896 // If the owning node has an exception, register the checkpoint to the
897 // predecessor so that the checkpoint is used for both the normal and the
898 // exceptional paths. Yes, this is a terrible hack and we might want
899 // to use an explicit frame state for the exceptional path.
900 if (owner_has_exception) {
901 liveness_block()->GetPredecessor()->Checkpoint(result);
902 } else {
903 liveness_block()->Checkpoint(result);
904 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000905 }
906 return result;
907}
908
909
910bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
911 return FLAG_analyze_environment_liveness &&
912 builder()->info()->is_deoptimization_enabled();
913}
914
915
916bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
917 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
918 (liveness_block() == nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919}
920
921
922AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
923 Expression::Context kind)
924 : kind_(kind), owner_(own), outer_(own->ast_context()) {
925 owner()->set_ast_context(this); // Push.
926#ifdef DEBUG
927 original_height_ = environment()->stack_height();
928#endif
929}
930
931
932AstGraphBuilder::AstContext::~AstContext() {
933 owner()->set_ast_context(outer_); // Pop.
934}
935
936
937AstGraphBuilder::AstEffectContext::~AstEffectContext() {
938 DCHECK(environment()->stack_height() == original_height_);
939}
940
941
942AstGraphBuilder::AstValueContext::~AstValueContext() {
943 DCHECK(environment()->stack_height() == original_height_ + 1);
944}
945
946
947AstGraphBuilder::AstTestContext::~AstTestContext() {
948 DCHECK(environment()->stack_height() == original_height_ + 1);
949}
950
951
952void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
953 // The value is ignored.
954}
955
956
957void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
958 environment()->Push(value);
959}
960
961
962void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964}
965
966
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968
969
970Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
971 return environment()->Pop();
972}
973
974
975Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
976 return environment()->Pop();
977}
978
979
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980Scope* AstGraphBuilder::current_scope() const {
981 return execution_context_->scope();
982}
983
984
985Node* AstGraphBuilder::current_context() const {
986 return environment()->Context();
987}
988
989
990void AstGraphBuilder::ControlScope::PerformCommand(Command command,
991 Statement* target,
992 Node* value) {
993 Environment* env = environment()->CopyAsUnreachable();
994 ControlScope* current = this;
995 while (current != nullptr) {
996 environment()->TrimStack(current->stack_height());
997 environment()->TrimContextChain(current->context_length());
998 if (current->Execute(command, target, value)) break;
999 current = current->outer_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 builder()->set_environment(env);
1002 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003}
1004
1005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
1007 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008}
1009
1010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
1012 PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
1013}
1014
1015
1016void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
1017 PerformCommand(CMD_RETURN, nullptr, return_value);
1018}
1019
1020
1021void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
1022 PerformCommand(CMD_THROW, nullptr, exception_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023}
1024
1025
1026void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 if (expr == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 return environment()->Push(jsgraph()->NullConstant());
1029 }
1030 VisitForValue(expr);
1031}
1032
1033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1035 if (expr == nullptr) {
1036 return environment()->Push(jsgraph()->TheHoleConstant());
1037 }
1038 VisitForValue(expr);
1039}
1040
1041
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1043 for (int i = 0; i < exprs->length(); ++i) {
1044 VisitForValue(exprs->at(i));
1045 }
1046}
1047
1048
1049void AstGraphBuilder::VisitForValue(Expression* expr) {
1050 AstValueContext for_value(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001051 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 } else {
1054 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 }
1056}
1057
1058
1059void AstGraphBuilder::VisitForEffect(Expression* expr) {
1060 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001061 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001063 } else {
1064 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 }
1066}
1067
1068
1069void AstGraphBuilder::VisitForTest(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 AstTestContext for_condition(this, expr->test_id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001071 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073 } else {
1074 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1075 }
1076}
1077
1078
1079void AstGraphBuilder::Visit(Expression* expr) {
1080 // Reuses enclosing AstContext.
1081 if (!CheckStackOverflow()) {
1082 expr->Accept(this);
1083 } else {
1084 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 }
1086}
1087
1088
1089void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1090 Variable* variable = decl->proxy()->var();
1091 VariableMode mode = decl->mode();
1092 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
1093 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 case VariableLocation::GLOBAL:
1095 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 Handle<Oddball> value = variable->binding_needs_init()
1097 ? isolate()->factory()->the_hole_value()
1098 : isolate()->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001099 globals()->push_back(variable->name());
1100 globals()->push_back(value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001101 break;
1102 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 case VariableLocation::PARAMETER:
1104 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 if (hole_init) {
1106 Node* value = jsgraph()->TheHoleConstant();
1107 environment()->Bind(variable, value);
1108 }
1109 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001110 case VariableLocation::CONTEXT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 if (hole_init) {
1112 Node* value = jsgraph()->TheHoleConstant();
1113 const Operator* op = javascript()->StoreContext(0, variable->index());
1114 NewNode(op, current_context(), value);
1115 }
1116 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 UNIMPLEMENTED();
1119 }
1120}
1121
1122
1123void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1124 Variable* variable = decl->proxy()->var();
1125 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 case VariableLocation::GLOBAL:
1127 case VariableLocation::UNALLOCATED: {
1128 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1129 decl->fun(), info()->script(), info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 // Check for stack-overflow exception.
1131 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001132 globals()->push_back(variable->name());
1133 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001134 break;
1135 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 case VariableLocation::PARAMETER:
1137 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001138 VisitForValue(decl->fun());
1139 Node* value = environment()->Pop();
1140 environment()->Bind(variable, value);
1141 break;
1142 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 VisitForValue(decl->fun());
1145 Node* value = environment()->Pop();
1146 const Operator* op = javascript()->StoreContext(0, variable->index());
1147 NewNode(op, current_context(), value);
1148 break;
1149 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 UNIMPLEMENTED();
1152 }
1153}
1154
1155
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001156void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1157 UNREACHABLE();
1158}
1159
1160
1161void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1162 UNREACHABLE();
1163}
1164
1165
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166void AstGraphBuilder::VisitBlock(Block* stmt) {
1167 BlockBuilder block(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 ControlScopeForBreakable scope(this, stmt, &block);
1169 if (stmt->labels() != nullptr) block.BeginBlock();
1170 if (stmt->scope() == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001171 // Visit statements in the same scope, no declarations.
1172 VisitStatements(stmt->statements());
1173 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 // Visit declarations and statements in a block scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 if (stmt->scope()->NeedsContext()) {
1176 Node* context = BuildLocalBlockContext(stmt->scope());
1177 ContextScope scope(this, stmt->scope(), context);
1178 VisitDeclarations(stmt->scope()->declarations());
1179 VisitStatements(stmt->statements());
1180 } else {
1181 VisitDeclarations(stmt->scope()->declarations());
1182 VisitStatements(stmt->statements());
1183 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 if (stmt->labels() != nullptr) block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186}
1187
1188
1189void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1190 VisitForEffect(stmt->expression());
1191}
1192
1193
1194void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1195 // Do nothing.
1196}
1197
1198
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1200 SloppyBlockFunctionStatement* stmt) {
1201 Visit(stmt->statement());
1202}
1203
1204
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1206 IfBuilder compare_if(this);
1207 VisitForTest(stmt->condition());
1208 Node* condition = environment()->Pop();
1209 compare_if.If(condition);
1210 compare_if.Then();
1211 Visit(stmt->then_statement());
1212 compare_if.Else();
1213 Visit(stmt->else_statement());
1214 compare_if.End();
1215}
1216
1217
1218void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 execution_control()->ContinueTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220}
1221
1222
1223void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 execution_control()->BreakTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225}
1226
1227
1228void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1229 VisitForValue(stmt->expression());
1230 Node* result = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001231 execution_control()->ReturnValue(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001232}
1233
1234
1235void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1236 VisitForValue(stmt->expression());
1237 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 Node* object = BuildToObject(value, stmt->ToObjectId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001239 const Operator* op = javascript()->CreateWithContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 Node* context = NewNode(op, object, GetFunctionClosureForContext());
1241 PrepareFrameState(context, stmt->EntryId());
1242 VisitInScope(stmt->statement(), stmt->scope(), context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243}
1244
1245
1246void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1247 ZoneList<CaseClause*>* clauses = stmt->cases();
1248 SwitchBuilder compare_switch(this, clauses->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 ControlScopeForBreakable scope(this, stmt, &compare_switch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001250 compare_switch.BeginSwitch();
1251 int default_index = -1;
1252
1253 // Keep the switch value on the stack until a case matches.
1254 VisitForValue(stmt->tag());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255
1256 // Iterate over all cases and create nodes for label comparison.
1257 for (int i = 0; i < clauses->length(); i++) {
1258 CaseClause* clause = clauses->at(i);
1259
1260 // The default is not a test, remember index.
1261 if (clause->is_default()) {
1262 default_index = i;
1263 continue;
1264 }
1265
1266 // Create nodes to perform label comparison as if via '==='. The switch
1267 // value is still on the operand stack while the label is evaluated.
1268 VisitForValue(clause->label());
1269 Node* label = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 Node* tag = environment()->Top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 const Operator* op = javascript()->StrictEqual();
1272 Node* condition = NewNode(op, tag, label);
1273 compare_switch.BeginLabel(i, condition);
1274
1275 // Discard the switch value at label match.
1276 environment()->Pop();
1277 compare_switch.EndLabel();
1278 }
1279
1280 // Discard the switch value and mark the default case.
1281 environment()->Pop();
1282 if (default_index >= 0) {
1283 compare_switch.DefaultAt(default_index);
1284 }
1285
1286 // Iterate over all cases and create nodes for case bodies.
1287 for (int i = 0; i < clauses->length(); i++) {
1288 CaseClause* clause = clauses->at(i);
1289 compare_switch.BeginCase(i);
1290 VisitStatements(clause->statements());
1291 compare_switch.EndCase();
1292 }
1293
1294 compare_switch.EndSwitch();
1295}
1296
1297
1298void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1299 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1301 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 while_loop.EndBody();
1303 VisitForTest(stmt->cond());
1304 Node* condition = environment()->Pop();
1305 while_loop.BreakUnless(condition);
1306 while_loop.EndLoop();
1307}
1308
1309
1310void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1311 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 VisitForTest(stmt->cond());
1314 Node* condition = environment()->Pop();
1315 while_loop.BreakUnless(condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 while_loop.EndBody();
1318 while_loop.EndLoop();
1319}
1320
1321
1322void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1323 LoopBuilder for_loop(this);
1324 VisitIfNotNull(stmt->init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001325 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1326 if (stmt->cond() != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001327 VisitForTest(stmt->cond());
1328 Node* condition = environment()->Pop();
1329 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001330 } else {
1331 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 for_loop.EndBody();
1335 VisitIfNotNull(stmt->next());
1336 for_loop.EndLoop();
1337}
1338
1339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1341 VisitForValue(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342 Node* object = environment()->Pop();
1343 BlockBuilder for_block(this);
1344 for_block.BeginBlock();
1345 // Check for null or undefined before entering loop.
1346 Node* is_null_cond =
1347 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1348 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1349 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1350 jsgraph()->UndefinedConstant());
1351 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 // Convert object to jsobject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354 object = BuildToObject(object, stmt->ToObjectId());
1355 environment()->Push(object);
1356
1357 // Prepare for-in cache.
1358 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001359 PrepareFrameState(prepare, stmt->PrepareId(),
1360 OutputFrameStateCombine::Push(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361 Node* cache_type = NewNode(common()->Projection(0), prepare);
1362 Node* cache_array = NewNode(common()->Projection(1), prepare);
1363 Node* cache_length = NewNode(common()->Projection(2), prepare);
1364
1365 // Construct the rest of the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 environment()->Push(cache_type);
1367 environment()->Push(cache_array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001368 environment()->Push(cache_length);
1369 environment()->Push(jsgraph()->ZeroConstant());
1370
1371 // Build the actual loop body.
1372 LoopBuilder for_loop(this);
1373 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 // These stack values are renamed in the case of OSR, so reload them
1376 // from the environment.
1377 Node* index = environment()->Peek(0);
1378 Node* cache_length = environment()->Peek(1);
1379 Node* cache_array = environment()->Peek(2);
1380 Node* cache_type = environment()->Peek(3);
1381 Node* object = environment()->Peek(4);
1382
1383 // Check loop termination condition.
1384 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1385 for_loop.BreakWhen(exit_cond);
1386
1387 // Compute the next enumerated value.
1388 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1389 cache_type, index);
1390 PrepareFrameState(value, stmt->FilterId(),
1391 OutputFrameStateCombine::Push());
1392 IfBuilder test_value(this);
1393 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1394 jsgraph()->UndefinedConstant());
1395 test_value.If(test_value_cond, BranchHint::kFalse);
1396 test_value.Then();
1397 test_value.Else();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 // Bind value and do loop body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001400 VectorSlotPair feedback =
1401 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1402 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1403 stmt->AssignmentId());
1404 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001406 test_value.End();
1407 index = environment()->Peek(0);
1408 for_loop.EndBody();
1409
1410 // Increment counter and continue.
1411 index = NewNode(javascript()->ForInStep(), index);
1412 environment()->Poke(0, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 for_loop.EndLoop();
1415 environment()->Drop(5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001417 for_block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418}
1419
1420
1421void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 LoopBuilder for_loop(this);
1423 VisitForEffect(stmt->assign_iterator());
1424 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1425 VisitForEffect(stmt->next_result());
1426 VisitForTest(stmt->result_done());
1427 Node* condition = environment()->Pop();
1428 for_loop.BreakWhen(condition);
1429 VisitForEffect(stmt->assign_each());
1430 VisitIterationBody(stmt, &for_loop);
1431 for_loop.EndBody();
1432 for_loop.EndLoop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433}
1434
1435
1436void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001437 TryCatchBuilder try_control(this);
1438
1439 // Evaluate the try-block inside a control scope. This simulates a handler
1440 // that is intercepting 'throw' control commands.
1441 try_control.BeginTry();
1442 {
1443 ControlScopeForCatch scope(this, &try_control);
1444 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1445 environment()->Push(current_context());
1446 Visit(stmt->try_block());
1447 environment()->Pop();
1448 }
1449 try_control.EndTry();
1450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451 // Clear message object as we enter the catch block.
1452 Node* the_hole = jsgraph()->TheHoleConstant();
1453 NewNode(javascript()->StoreMessage(), the_hole);
1454
1455 // Create a catch scope that binds the exception.
1456 Node* exception = try_control.GetExceptionNode();
1457 Handle<String> name = stmt->variable()->name();
1458 const Operator* op = javascript()->CreateCatchContext(name);
1459 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1460
1461 // Evaluate the catch-block.
1462 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1463 try_control.EndCatch();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464}
1465
1466
1467void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001468 TryFinallyBuilder try_control(this);
1469
1470 // We keep a record of all paths that enter the finally-block to be able to
1471 // dispatch to the correct continuation point after the statements in the
1472 // finally-block have been evaluated.
1473 //
1474 // The try-finally construct can enter the finally-block in three ways:
1475 // 1. By exiting the try-block normally, falling through at the end.
1476 // 2. By exiting the try-block with a function-local control flow transfer
1477 // (i.e. through break/continue/return statements).
1478 // 3. By exiting the try-block with a thrown exception.
1479 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1480 ControlScope::DeferredCommands* commands =
1481 new (local_zone()) ControlScope::DeferredCommands(this);
1482
1483 // Evaluate the try-block inside a control scope. This simulates a handler
1484 // that is intercepting all control commands.
1485 try_control.BeginTry();
1486 {
1487 ControlScopeForFinally scope(this, commands, &try_control);
1488 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1489 environment()->Push(current_context());
1490 Visit(stmt->try_block());
1491 environment()->Pop();
1492 }
1493 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 // The result value semantics depend on how the block was entered:
1496 // - ReturnStatement: It represents the return value being returned.
1497 // - ThrowStatement: It represents the exception being thrown.
1498 // - BreakStatement/ContinueStatement: Filled with the hole.
1499 // - Falling through into finally-block: Filled with the hole.
1500 Node* result = try_control.GetResultValueNode();
1501 Node* token = try_control.GetDispatchTokenNode();
1502
1503 // The result value, dispatch token and message is expected on the operand
1504 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1505 Node* message = NewNode(javascript()->LoadMessage());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001506 environment()->Push(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001507 environment()->Push(result);
1508 environment()->Push(message);
1509
1510 // Clear message object as we enter the finally block.
1511 Node* the_hole = jsgraph()->TheHoleConstant();
1512 NewNode(javascript()->StoreMessage(), the_hole);
1513
1514 // Evaluate the finally-block.
1515 Visit(stmt->finally_block());
1516 try_control.EndFinally();
1517
1518 // The result value, dispatch token and message is restored from the operand
1519 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1520 message = environment()->Pop();
1521 result = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001522 token = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523 NewNode(javascript()->StoreMessage(), message);
1524
1525 // Dynamic dispatch after the finally-block.
1526 commands->ApplyDeferredCommands(token, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527}
1528
1529
1530void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 Node* node =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001532 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 PrepareFrameState(node, stmt->DebugBreakId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 environment()->MarkAllLocalsLive();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535}
1536
1537
1538void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539 // Find or build a shared function info.
1540 Handle<SharedFunctionInfo> shared_info =
1541 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1542 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543
1544 // Create node to instantiate a new closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1546 const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1547 Node* value = NewNode(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001548 ast_context()->ProduceValue(value);
1549}
1550
1551
1552void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 // Visit declarations and class literal in a block scope.
1554 if (expr->scope()->ContextLocalCount() > 0) {
1555 Node* context = BuildLocalBlockContext(expr->scope());
1556 ContextScope scope(this, expr->scope(), context);
1557 VisitDeclarations(expr->scope()->declarations());
1558 VisitClassLiteralContents(expr);
1559 } else {
1560 VisitDeclarations(expr->scope()->declarations());
1561 VisitClassLiteralContents(expr);
1562 }
1563}
1564
1565
1566void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 VisitForValueOrTheHole(expr->extends());
1568 VisitForValue(expr->constructor());
1569
1570 // Create node to instantiate a new class.
1571 Node* constructor = environment()->Pop();
1572 Node* extends = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 Node* start = jsgraph()->Constant(expr->start_position());
1574 Node* end = jsgraph()->Constant(expr->end_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001575 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
1576 Node* literal = NewNode(opc, extends, constructor, start, end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 PrepareFrameState(literal, expr->CreateLiteralId(),
1578 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001579 environment()->Push(literal);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001580
1581 // Load the "prototype" from the constructor.
1582 FrameStateBeforeAndAfter states(this, expr->CreateLiteralId());
1583 Handle<Name> name = isolate()->factory()->prototype_string();
1584 VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
1585 Node* prototype = BuildNamedLoad(literal, name, pair);
1586 states.AddToNode(prototype, expr->PrototypeId(),
1587 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 environment()->Push(prototype);
1589
1590 // Create nodes to store method values into the literal.
1591 for (int i = 0; i < expr->properties()->length(); i++) {
1592 ObjectLiteral::Property* property = expr->properties()->at(i);
1593 environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1594
1595 VisitForValue(property->key());
1596 Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1597 environment()->Push(name);
1598
1599 // The static prototype property is read only. We handle the non computed
1600 // property name case in the parser. Since this is the only case where we
1601 // need to check for an own read only property we special case this so we do
1602 // not need to do this for every property.
1603 if (property->is_static() && property->is_computed_name()) {
1604 Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1605 expr->GetIdForProperty(i));
1606 environment()->Push(check);
1607 }
1608
1609 VisitForValue(property->value());
1610 Node* value = environment()->Pop();
1611 Node* key = environment()->Pop();
1612 Node* receiver = environment()->Pop();
1613
1614 BuildSetHomeObject(value, receiver, property);
1615
1616 switch (property->kind()) {
1617 case ObjectLiteral::Property::CONSTANT:
1618 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1619 case ObjectLiteral::Property::PROTOTYPE:
1620 UNREACHABLE();
1621 case ObjectLiteral::Property::COMPUTED: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001622 Node* attr = jsgraph()->Constant(DONT_ENUM);
1623 Node* set_function_name =
1624 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001626 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1627 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001628 break;
1629 }
1630 case ObjectLiteral::Property::GETTER: {
1631 Node* attr = jsgraph()->Constant(DONT_ENUM);
1632 const Operator* op = javascript()->CallRuntime(
1633 Runtime::kDefineGetterPropertyUnchecked, 4);
1634 NewNode(op, receiver, key, value, attr);
1635 break;
1636 }
1637 case ObjectLiteral::Property::SETTER: {
1638 Node* attr = jsgraph()->Constant(DONT_ENUM);
1639 const Operator* op = javascript()->CallRuntime(
1640 Runtime::kDefineSetterPropertyUnchecked, 4);
1641 NewNode(op, receiver, key, value, attr);
1642 break;
1643 }
1644 }
1645 }
1646
1647 // Set both the prototype and constructor to have fast properties, and also
1648 // freeze them in strong mode.
1649 prototype = environment()->Pop();
1650 literal = environment()->Pop();
1651 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001652 javascript()->CallRuntime(Runtime::kFinalizeClassDefinition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653 literal = NewNode(op, literal, prototype);
1654
1655 // Assign to class variable.
1656 if (expr->class_variable_proxy() != nullptr) {
1657 Variable* var = expr->class_variable_proxy()->var();
1658 FrameStateBeforeAndAfter states(this, BailoutId::None());
1659 VectorSlotPair feedback = CreateVectorSlotPair(
1660 expr->NeedsProxySlot() ? expr->ProxySlot()
1661 : FeedbackVectorSlot::Invalid());
1662 BuildVariableAssignment(var, literal, Token::INIT, feedback,
1663 BailoutId::None(), states);
1664 }
1665 ast_context()->ProduceValue(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001666}
1667
1668
1669void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1670 UNREACHABLE();
1671}
1672
1673
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001674void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1675 VisitBlock(expr->block());
1676 VisitVariableProxy(expr->result());
1677 ast_context()->ReplaceValue();
1678}
1679
1680
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681void AstGraphBuilder::VisitConditional(Conditional* expr) {
1682 IfBuilder compare_if(this);
1683 VisitForTest(expr->condition());
1684 Node* condition = environment()->Pop();
1685 compare_if.If(condition);
1686 compare_if.Then();
1687 Visit(expr->then_expression());
1688 compare_if.Else();
1689 Visit(expr->else_expression());
1690 compare_if.End();
1691 ast_context()->ReplaceValue();
1692}
1693
1694
1695void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001696 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001697 FrameStateBeforeAndAfter states(this, BeforeId(expr));
1698 Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
1699 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001700 ast_context()->ProduceValue(value);
1701}
1702
1703
1704void AstGraphBuilder::VisitLiteral(Literal* expr) {
1705 Node* value = jsgraph()->Constant(expr->value());
1706 ast_context()->ProduceValue(value);
1707}
1708
1709
1710void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1711 Node* closure = GetFunctionClosure();
1712
1713 // Create node to materialize a regular expression literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001714 const Operator* op = javascript()->CreateLiteralRegExp(
1715 expr->pattern(), expr->flags(), expr->literal_index());
1716 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001717 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001718 ast_context()->ProduceValue(literal);
1719}
1720
1721
1722void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1723 Node* closure = GetFunctionClosure();
1724
1725 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001726 const Operator* op = javascript()->CreateLiteralObject(
1727 expr->constant_properties(), expr->ComputeFlags(true),
1728 expr->literal_index());
1729 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001730 PrepareFrameState(literal, expr->CreateLiteralId(),
1731 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001732
1733 // The object is expected on the operand stack during computation of the
1734 // property values and is the value of the entire expression.
1735 environment()->Push(literal);
1736
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737 // Create nodes to store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001738 int property_index = 0;
1739 AccessorTable accessor_table(local_zone());
1740 for (; property_index < expr->properties()->length(); property_index++) {
1741 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1742 if (property->is_computed_name()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001743 if (property->IsCompileTimeValue()) continue;
1744
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001745 Literal* key = property->key()->AsLiteral();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746 switch (property->kind()) {
1747 case ObjectLiteral::Property::CONSTANT:
1748 UNREACHABLE();
1749 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1750 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1751 // Fall through.
1752 case ObjectLiteral::Property::COMPUTED: {
1753 // It is safe to use [[Put]] here because the boilerplate already
1754 // contains computed properties with an uninitialized value.
1755 if (key->value()->IsInternalizedString()) {
1756 if (property->emit_store()) {
1757 VisitForValue(property->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001758 FrameStateBeforeAndAfter states(this, property->value()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760 Node* literal = environment()->Top();
1761 Handle<Name> name = key->AsPropertyName();
1762 VectorSlotPair feedback =
1763 CreateVectorSlotPair(property->GetSlot(0));
1764 Node* store = BuildNamedStore(literal, name, value, feedback);
1765 states.AddToNode(store, key->id(),
1766 OutputFrameStateCombine::Ignore());
1767 BuildSetHomeObject(value, literal, property, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 } else {
1769 VisitForEffect(property->value());
1770 }
1771 break;
1772 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001773 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774 VisitForValue(property->key());
1775 VisitForValue(property->value());
1776 Node* value = environment()->Pop();
1777 Node* key = environment()->Pop();
1778 Node* receiver = environment()->Pop();
1779 if (property->emit_store()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001780 Node* language = jsgraph()->Constant(SLOPPY);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001781 const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 Node* set_property = NewNode(op, receiver, key, value, language);
1783 // SetProperty should not lazy deopt on an object literal.
1784 PrepareFrameState(set_property, BailoutId::None());
1785 BuildSetHomeObject(value, receiver, property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 }
1787 break;
1788 }
1789 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001791 VisitForValue(property->value());
1792 Node* value = environment()->Pop();
1793 Node* receiver = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001794 DCHECK(property->emit_store());
1795 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001796 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001797 Node* set_prototype = NewNode(op, receiver, value);
1798 // SetPrototype should not lazy deopt on an object literal.
1799 PrepareFrameState(set_prototype,
1800 expr->GetIdForPropertySet(property_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001801 break;
1802 }
1803 case ObjectLiteral::Property::GETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 if (property->emit_store()) {
1805 accessor_table.lookup(key)->second->getter = property;
1806 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807 break;
1808 case ObjectLiteral::Property::SETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001809 if (property->emit_store()) {
1810 accessor_table.lookup(key)->second->setter = property;
1811 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812 break;
1813 }
1814 }
1815
1816 // Create nodes to define accessors, using only a single call to the runtime
1817 // for each pair of corresponding getters and setters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 for (AccessorTable::Iterator it = accessor_table.begin();
1820 it != accessor_table.end(); ++it) {
1821 VisitForValue(it->first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 VisitObjectLiteralAccessor(literal, it->second->getter);
1823 VisitObjectLiteralAccessor(literal, it->second->setter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001824 Node* setter = environment()->Pop();
1825 Node* getter = environment()->Pop();
1826 Node* name = environment()->Pop();
1827 Node* attr = jsgraph()->Constant(NONE);
1828 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001829 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830 Node* call = NewNode(op, literal, name, getter, setter, attr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001831 // This should not lazy deopt on a new literal.
1832 PrepareFrameState(call, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 }
1834
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001835 // Object literals have two parts. The "static" part on the left contains no
1836 // computed property names, and so we can compute its map ahead of time; see
1837 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1838 // with the first computed property name and continues with all properties to
1839 // its right. All the code from above initializes the static component of the
1840 // object literal, and arranges for the map of the result to reflect the
1841 // static order in which the keys appear. For the dynamic properties, we
1842 // compile them into a series of "SetOwnProperty" runtime calls. This will
1843 // preserve insertion order.
1844 for (; property_index < expr->properties()->length(); property_index++) {
1845 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1846
1847 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1848 environment()->Push(environment()->Top()); // Duplicate receiver.
1849 VisitForValue(property->value());
1850 Node* value = environment()->Pop();
1851 Node* receiver = environment()->Pop();
1852 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001853 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001854 Node* call = NewNode(op, receiver, value);
1855 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1856 continue;
1857 }
1858
1859 environment()->Push(environment()->Top()); // Duplicate receiver.
1860 VisitForValue(property->key());
1861 Node* name = BuildToName(environment()->Pop(),
1862 expr->GetIdForPropertyName(property_index));
1863 environment()->Push(name);
1864 VisitForValue(property->value());
1865 Node* value = environment()->Pop();
1866 Node* key = environment()->Pop();
1867 Node* receiver = environment()->Pop();
1868 BuildSetHomeObject(value, receiver, property);
1869 switch (property->kind()) {
1870 case ObjectLiteral::Property::CONSTANT:
1871 case ObjectLiteral::Property::COMPUTED:
1872 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1873 Node* attr = jsgraph()->Constant(NONE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001874 Node* set_function_name =
1875 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001876 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001877 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1878 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001879 break;
1880 }
1881 case ObjectLiteral::Property::PROTOTYPE:
1882 UNREACHABLE(); // Handled specially above.
1883 break;
1884 case ObjectLiteral::Property::GETTER: {
1885 Node* attr = jsgraph()->Constant(NONE);
1886 const Operator* op = javascript()->CallRuntime(
1887 Runtime::kDefineGetterPropertyUnchecked, 4);
1888 Node* call = NewNode(op, receiver, key, value, attr);
1889 PrepareFrameState(call, BailoutId::None());
1890 break;
1891 }
1892 case ObjectLiteral::Property::SETTER: {
1893 Node* attr = jsgraph()->Constant(NONE);
1894 const Operator* op = javascript()->CallRuntime(
1895 Runtime::kDefineSetterPropertyUnchecked, 4);
1896 Node* call = NewNode(op, receiver, key, value, attr);
1897 PrepareFrameState(call, BailoutId::None());
1898 break;
1899 }
1900 }
1901 }
1902
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001903 // Transform literals that contain functions to fast properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001904 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001905 if (expr->has_function()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001906 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001907 NewNode(op, literal);
1908 }
1909
1910 ast_context()->ProduceValue(environment()->Pop());
1911}
1912
1913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914void AstGraphBuilder::VisitObjectLiteralAccessor(
1915 Node* home_object, ObjectLiteralProperty* property) {
1916 if (property == nullptr) {
1917 VisitForValueOrNull(nullptr);
1918 } else {
1919 VisitForValue(property->value());
1920 BuildSetHomeObject(environment()->Top(), home_object, property);
1921 }
1922}
1923
1924
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001925void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1926 Node* closure = GetFunctionClosure();
1927
1928 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001929 const Operator* op = javascript()->CreateLiteralArray(
1930 expr->constant_elements(), expr->ComputeFlags(true),
1931 expr->literal_index());
1932 Node* literal = NewNode(op, closure);
1933 PrepareFrameState(literal, expr->CreateLiteralId(),
1934 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001936 // The array is expected on the operand stack during computation of the
1937 // element values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001938 environment()->Push(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939
1940 // Create nodes to evaluate all the non-constant subexpressions and to store
1941 // them into the newly cloned array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001942 int array_index = 0;
1943 for (; array_index < expr->values()->length(); array_index++) {
1944 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001945 DCHECK(!subexpr->IsSpread());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001946 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1947
1948 VisitForValue(subexpr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001949 {
1950 FrameStateBeforeAndAfter states(this, subexpr->id());
1951 VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1952 Node* value = environment()->Pop();
1953 Node* index = jsgraph()->Constant(array_index);
1954 Node* literal = environment()->Top();
1955 Node* store = BuildKeyedStore(literal, index, value, pair);
1956 states.AddToNode(store, expr->GetIdForElement(array_index),
1957 OutputFrameStateCombine::Ignore());
1958 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001959 }
1960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001961 // In case the array literal contains spread expressions it has two parts. The
1962 // first part is the "static" array which has a literal index is handled
1963 // above. The second part is the part after the first spread expression
1964 // (inclusive) and these elements gets appended to the array. Note that the
1965 // number elements an iterable produces is unknown ahead of time.
1966 for (; array_index < expr->values()->length(); array_index++) {
1967 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001968 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001969
Ben Murdoch097c5b22016-05-18 11:27:45 +01001970 VisitForValue(subexpr);
1971 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001972 Node* value = environment()->Pop();
1973 Node* array = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001974 const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
1975 Node* result = NewNode(op, array, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001976 PrepareFrameState(result, expr->GetIdForElement(array_index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001977 environment()->Push(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001978 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001979 }
1980
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001981 ast_context()->ProduceValue(environment()->Pop());
1982}
1983
1984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001985void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
1986 const VectorSlotPair& feedback,
1987 BailoutId bailout_id_before,
1988 BailoutId bailout_id_after) {
1989 DCHECK(expr->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001990
1991 // Left-hand side can only be a property, a global or a variable slot.
1992 Property* property = expr->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001993 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001994
1995 // Evaluate LHS expression and store the value.
1996 switch (assign_type) {
1997 case VARIABLE: {
1998 Variable* var = expr->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001999 environment()->Push(value);
2000 FrameStateBeforeAndAfter states(this, bailout_id_before);
2001 value = environment()->Pop();
2002 BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
2003 bailout_id_after, states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004 break;
2005 }
2006 case NAMED_PROPERTY: {
2007 environment()->Push(value);
2008 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002009 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002010 Node* object = environment()->Pop();
2011 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002012 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2013 Node* store = BuildNamedStore(object, name, value, feedback);
2014 states.AddToNode(store, bailout_id_after,
2015 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002016 break;
2017 }
2018 case KEYED_PROPERTY: {
2019 environment()->Push(value);
2020 VisitForValue(property->obj());
2021 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002023 Node* key = environment()->Pop();
2024 Node* object = environment()->Pop();
2025 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002026 Node* store = BuildKeyedStore(object, key, value, feedback);
2027 states.AddToNode(store, bailout_id_after,
2028 OutputFrameStateCombine::Ignore());
2029 break;
2030 }
2031 case NAMED_SUPER_PROPERTY: {
2032 environment()->Push(value);
2033 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2034 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2035 FrameStateBeforeAndAfter states(this, property->obj()->id());
2036 Node* home_object = environment()->Pop();
2037 Node* receiver = environment()->Pop();
2038 value = environment()->Pop();
2039 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2040 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2041 states.AddToNode(store, bailout_id_after,
2042 OutputFrameStateCombine::Ignore());
2043 break;
2044 }
2045 case KEYED_SUPER_PROPERTY: {
2046 environment()->Push(value);
2047 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2048 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2049 VisitForValue(property->key());
2050 FrameStateBeforeAndAfter states(this, property->key()->id());
2051 Node* key = environment()->Pop();
2052 Node* home_object = environment()->Pop();
2053 Node* receiver = environment()->Pop();
2054 value = environment()->Pop();
2055 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2056 states.AddToNode(store, bailout_id_after,
2057 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002058 break;
2059 }
2060 }
2061}
2062
2063
2064void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002065 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002066
2067 // Left-hand side can only be a property, a global or a variable slot.
2068 Property* property = expr->target()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002069 LhsKind assign_type = Property::GetAssignType(property);
2070 bool needs_frame_state_before = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071
2072 // Evaluate LHS expression.
2073 switch (assign_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002074 case VARIABLE: {
2075 Variable* variable = expr->target()->AsVariableProxy()->var();
2076 if (variable->location() == VariableLocation::PARAMETER ||
2077 variable->location() == VariableLocation::LOCAL ||
2078 variable->location() == VariableLocation::CONTEXT) {
2079 needs_frame_state_before = false;
2080 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002081 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002082 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002083 case NAMED_PROPERTY:
2084 VisitForValue(property->obj());
2085 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002086 case KEYED_PROPERTY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087 VisitForValue(property->obj());
2088 VisitForValue(property->key());
2089 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002090 case NAMED_SUPER_PROPERTY:
2091 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2092 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2093 break;
2094 case KEYED_SUPER_PROPERTY:
2095 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2096 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2097 VisitForValue(property->key());
2098 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002099 }
2100
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002101 BailoutId before_store_id = BailoutId::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002102 // Evaluate the value and potentially handle compound assignments by loading
2103 // the left-hand side value and performing a binary operation.
2104 if (expr->is_compound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002105 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002106 switch (assign_type) {
2107 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002108 VariableProxy* proxy = expr->target()->AsVariableProxy();
2109 VectorSlotPair pair =
2110 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002111 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2112 old_value =
2113 BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
2114 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002115 break;
2116 }
2117 case NAMED_PROPERTY: {
2118 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002119 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002120 VectorSlotPair pair =
2121 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002122 FrameStateBeforeAndAfter states(this, property->obj()->id());
2123 old_value = BuildNamedLoad(object, name, pair);
2124 states.AddToNode(old_value, property->LoadId(),
2125 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002126 break;
2127 }
2128 case KEYED_PROPERTY: {
2129 Node* key = environment()->Top();
2130 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002131 VectorSlotPair pair =
2132 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002133 FrameStateBeforeAndAfter states(this, property->key()->id());
2134 old_value = BuildKeyedLoad(object, key, pair);
2135 states.AddToNode(old_value, property->LoadId(),
2136 OutputFrameStateCombine::Push());
2137 break;
2138 }
2139 case NAMED_SUPER_PROPERTY: {
2140 Node* home_object = environment()->Top();
2141 Node* receiver = environment()->Peek(1);
2142 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2143 VectorSlotPair pair =
2144 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2145 FrameStateBeforeAndAfter states(this, property->obj()->id());
2146 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2147 states.AddToNode(old_value, property->LoadId(),
2148 OutputFrameStateCombine::Push());
2149 break;
2150 }
2151 case KEYED_SUPER_PROPERTY: {
2152 Node* key = environment()->Top();
2153 Node* home_object = environment()->Peek(1);
2154 Node* receiver = environment()->Peek(2);
2155 VectorSlotPair pair =
2156 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2157 FrameStateBeforeAndAfter states(this, property->key()->id());
2158 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2159 states.AddToNode(old_value, property->LoadId(),
2160 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002161 break;
2162 }
2163 }
2164 environment()->Push(old_value);
2165 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002166 Node* value;
2167 {
2168 FrameStateBeforeAndAfter states(this, expr->value()->id());
2169 Node* right = environment()->Pop();
2170 Node* left = environment()->Pop();
2171 value =
2172 BuildBinaryOp(left, right, expr->binary_op(),
2173 expr->binary_operation()->BinaryOperationFeedbackId());
2174 states.AddToNode(value, expr->binary_operation()->id(),
2175 OutputFrameStateCombine::Push());
2176 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002177 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 if (needs_frame_state_before) {
2179 before_store_id = expr->binary_operation()->id();
2180 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002181 } else {
2182 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002183 if (needs_frame_state_before) {
2184 before_store_id = expr->value()->id();
2185 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002186 }
2187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002188 FrameStateBeforeAndAfter store_states(this, before_store_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002189 // Store the value.
2190 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191 VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002192 switch (assign_type) {
2193 case VARIABLE: {
2194 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002195 BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2196 store_states, ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002197 break;
2198 }
2199 case NAMED_PROPERTY: {
2200 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2202 Node* store = BuildNamedStore(object, name, value, feedback);
2203 store_states.AddToNode(store, expr->id(),
2204 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002205 break;
2206 }
2207 case KEYED_PROPERTY: {
2208 Node* key = environment()->Pop();
2209 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002210 Node* store = BuildKeyedStore(object, key, value, feedback);
2211 store_states.AddToNode(store, expr->id(),
2212 ast_context()->GetStateCombine());
2213 break;
2214 }
2215 case NAMED_SUPER_PROPERTY: {
2216 Node* home_object = environment()->Pop();
2217 Node* receiver = environment()->Pop();
2218 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2219 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2220 store_states.AddToNode(store, expr->id(),
2221 ast_context()->GetStateCombine());
2222 break;
2223 }
2224 case KEYED_SUPER_PROPERTY: {
2225 Node* key = environment()->Pop();
2226 Node* home_object = environment()->Pop();
2227 Node* receiver = environment()->Pop();
2228 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2229 store_states.AddToNode(store, expr->id(),
2230 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002231 break;
2232 }
2233 }
2234
2235 ast_context()->ProduceValue(value);
2236}
2237
2238
2239void AstGraphBuilder::VisitYield(Yield* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240 // TODO(turbofan): Implement yield here.
2241 SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002242 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2243}
2244
2245
2246void AstGraphBuilder::VisitThrow(Throw* expr) {
2247 VisitForValue(expr->exception());
2248 Node* exception = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002249 Node* value = BuildThrowError(exception, expr->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002250 ast_context()->ProduceValue(value);
2251}
2252
2253
2254void AstGraphBuilder::VisitProperty(Property* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002255 Node* value = nullptr;
2256 LhsKind property_kind = Property::GetAssignType(expr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002257 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002258 switch (property_kind) {
2259 case VARIABLE:
2260 UNREACHABLE();
2261 break;
2262 case NAMED_PROPERTY: {
2263 VisitForValue(expr->obj());
2264 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2265 Node* object = environment()->Pop();
2266 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2267 value = BuildNamedLoad(object, name, pair);
2268 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2269 break;
2270 }
2271 case KEYED_PROPERTY: {
2272 VisitForValue(expr->obj());
2273 VisitForValue(expr->key());
2274 FrameStateBeforeAndAfter states(this, expr->key()->id());
2275 Node* key = environment()->Pop();
2276 Node* object = environment()->Pop();
2277 value = BuildKeyedLoad(object, key, pair);
2278 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2279 break;
2280 }
2281 case NAMED_SUPER_PROPERTY: {
2282 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2283 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2284 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2285 Node* home_object = environment()->Pop();
2286 Node* receiver = environment()->Pop();
2287 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2288 value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2289 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2290 break;
2291 }
2292 case KEYED_SUPER_PROPERTY: {
2293 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2294 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2295 VisitForValue(expr->key());
2296 FrameStateBeforeAndAfter states(this, expr->key()->id());
2297 Node* key = environment()->Pop();
2298 Node* home_object = environment()->Pop();
2299 Node* receiver = environment()->Pop();
2300 value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2301 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2302 break;
2303 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002304 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002305 ast_context()->ProduceValue(value);
2306}
2307
2308
2309void AstGraphBuilder::VisitCall(Call* expr) {
2310 Expression* callee = expr->expression();
2311 Call::CallType call_type = expr->GetCallType(isolate());
2312
2313 // Prepare the callee and the receiver to the function call. This depends on
2314 // the semantics of the underlying call type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002315 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2316 Node* receiver_value = nullptr;
2317 Node* callee_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002318 bool possibly_eval = false;
2319 switch (call_type) {
2320 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002321 VariableProxy* proxy = callee->AsVariableProxy();
2322 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002323 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002324 callee_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002325 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2326 pair, OutputFrameStateCombine::Push());
2327 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002328 receiver_value = jsgraph()->UndefinedConstant();
2329 break;
2330 }
2331 case Call::LOOKUP_SLOT_CALL: {
2332 Variable* variable = callee->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002333 DCHECK(variable->location() == VariableLocation::LOOKUP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002334 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002335 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002336 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2337 Node* pair = NewNode(op, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 callee_value = NewNode(common()->Projection(0), pair);
2339 receiver_value = NewNode(common()->Projection(1), pair);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002340 PrepareFrameState(pair, expr->LookupId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002341 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002342 break;
2343 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002344 case Call::NAMED_PROPERTY_CALL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002345 Property* property = callee->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002346 VectorSlotPair feedback =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002347 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002348 VisitForValue(property->obj());
2349 FrameStateBeforeAndAfter states(this, property->obj()->id());
2350 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2351 Node* object = environment()->Top();
2352 callee_value = BuildNamedLoad(object, name, feedback);
2353 states.AddToNode(callee_value, property->LoadId(),
2354 OutputFrameStateCombine::Push());
2355 // Note that a property call requires the receiver to be wrapped into
2356 // an object for sloppy callees. However the receiver is guaranteed
2357 // not to be null or undefined at this point.
2358 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002359 receiver_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002360 break;
2361 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002362 case Call::KEYED_PROPERTY_CALL: {
2363 Property* property = callee->AsProperty();
2364 VectorSlotPair feedback =
2365 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2366 VisitForValue(property->obj());
2367 VisitForValue(property->key());
2368 FrameStateBeforeAndAfter states(this, property->key()->id());
2369 Node* key = environment()->Pop();
2370 Node* object = environment()->Top();
2371 callee_value = BuildKeyedLoad(object, key, feedback);
2372 states.AddToNode(callee_value, property->LoadId(),
2373 OutputFrameStateCombine::Push());
2374 // Note that a property call requires the receiver to be wrapped into
2375 // an object for sloppy callees. However the receiver is guaranteed
2376 // not to be null or undefined at this point.
2377 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2378 receiver_value = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002379 break;
2380 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002381 case Call::NAMED_SUPER_PROPERTY_CALL: {
2382 Property* property = callee->AsProperty();
2383 SuperPropertyReference* super_ref =
2384 property->obj()->AsSuperPropertyReference();
2385 VisitForValue(super_ref->home_object());
2386 VisitForValue(super_ref->this_var());
2387 Node* home = environment()->Peek(1);
2388 Node* object = environment()->Top();
2389 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2390 FrameStateBeforeAndAfter states(this, property->obj()->id());
2391 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
2392 states.AddToNode(callee_value, property->LoadId(),
2393 OutputFrameStateCombine::Push());
2394 // Note that a property call requires the receiver to be wrapped into
2395 // an object for sloppy callees. Since the receiver is not the target of
2396 // the load, it could very well be null or undefined at this point.
2397 receiver_value = environment()->Pop();
2398 environment()->Drop(1);
2399 break;
2400 }
2401 case Call::KEYED_SUPER_PROPERTY_CALL: {
2402 Property* property = callee->AsProperty();
2403 SuperPropertyReference* super_ref =
2404 property->obj()->AsSuperPropertyReference();
2405 VisitForValue(super_ref->home_object());
2406 VisitForValue(super_ref->this_var());
2407 environment()->Push(environment()->Top()); // Duplicate this_var.
2408 environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
2409 VisitForValue(property->key());
2410 Node* key = environment()->Pop();
2411 Node* home = environment()->Pop();
2412 Node* object = environment()->Pop();
2413 FrameStateBeforeAndAfter states(this, property->key()->id());
2414 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
2415 states.AddToNode(callee_value, property->LoadId(),
2416 OutputFrameStateCombine::Push());
2417 // Note that a property call requires the receiver to be wrapped into
2418 // an object for sloppy callees. Since the receiver is not the target of
2419 // the load, it could very well be null or undefined at this point.
2420 receiver_value = environment()->Pop();
2421 environment()->Drop(1);
2422 break;
2423 }
2424 case Call::SUPER_CALL:
2425 return VisitCallSuper(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002426 case Call::POSSIBLY_EVAL_CALL:
2427 possibly_eval = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002428 if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2429 Variable* variable = callee->AsVariableProxy()->var();
2430 Node* name = jsgraph()->Constant(variable->name());
2431 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002432 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2433 Node* pair = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002434 callee_value = NewNode(common()->Projection(0), pair);
2435 receiver_value = NewNode(common()->Projection(1), pair);
2436 PrepareFrameState(pair, expr->LookupId(),
2437 OutputFrameStateCombine::Push(2));
2438 break;
2439 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440 // Fall through.
2441 case Call::OTHER_CALL:
2442 VisitForValue(callee);
2443 callee_value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002444 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002445 receiver_value = jsgraph()->UndefinedConstant();
2446 break;
2447 }
2448
2449 // The callee and the receiver both have to be pushed onto the operand stack
2450 // before arguments are being evaluated.
2451 environment()->Push(callee_value);
2452 environment()->Push(receiver_value);
2453
2454 // Evaluate all arguments to the function call,
2455 ZoneList<Expression*>* args = expr->arguments();
2456 VisitForValues(args);
2457
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002458 // Resolve callee for a potential direct eval call. This block will mutate the
2459 // callee value pushed onto the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002460 if (possibly_eval && args->length() > 0) {
2461 int arg_count = args->length();
2462
2463 // Extract callee and source string from the environment.
2464 Node* callee = environment()->Peek(arg_count + 1);
2465 Node* source = environment()->Peek(arg_count - 1);
2466
2467 // Create node to ask for help resolving potential eval call. This will
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002468 // provide a fully resolved callee to patch into the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002469 Node* function = GetFunctionClosure();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002470 Node* language = jsgraph()->Constant(language_mode());
2471 Node* position = jsgraph()->Constant(current_scope()->start_position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002472 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002473 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002474 Node* new_callee =
2475 NewNode(op, callee, source, function, language, position);
2476 PrepareFrameState(new_callee, expr->EvalId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002477 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002479 // Patch callee on the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002480 environment()->Poke(arg_count + 1, new_callee);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002481 }
2482
2483 // Create node to perform the function call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2485 const Operator* call = javascript()->CallFunction(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002486 args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002487 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002489 environment()->Push(value->InputAt(0)); // The callee passed to the call.
2490 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2491 environment()->Drop(1);
2492 ast_context()->ProduceValue(value);
2493}
2494
2495
2496void AstGraphBuilder::VisitCallSuper(Call* expr) {
2497 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2498 DCHECK_NOT_NULL(super);
2499
2500 // Prepare the callee to the super call.
2501 VisitForValue(super->this_function_var());
2502 Node* this_function = environment()->Pop();
2503 const Operator* op =
2504 javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2505 Node* super_function = NewNode(op, this_function);
2506 environment()->Push(super_function);
2507
2508 // Evaluate all arguments to the super call.
2509 ZoneList<Expression*>* args = expr->arguments();
2510 VisitForValues(args);
2511
2512 // The new target is loaded from the {new.target} variable.
2513 VisitForValue(super->new_target_var());
2514
2515 // Create node to perform the super call.
2516 const Operator* call =
2517 javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
2518 FrameStateBeforeAndAfter states(this, super->new_target_var()->id());
2519 Node* value = ProcessArguments(call, args->length() + 2);
2520 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002521 ast_context()->ProduceValue(value);
2522}
2523
2524
2525void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2526 VisitForValue(expr->expression());
2527
2528 // Evaluate all arguments to the construct call.
2529 ZoneList<Expression*>* args = expr->arguments();
2530 VisitForValues(args);
2531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002532 // The baseline compiler doesn't push the new.target, so we need to record
2533 // the frame state before the push.
2534 FrameStateBeforeAndAfter states(
2535 this, args->is_empty() ? expr->expression()->id() : args->last()->id());
2536
2537 // The new target is the same as the callee.
2538 environment()->Push(environment()->Peek(args->length()));
2539
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002540 // Create node to perform the construct call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2542 const Operator* call =
2543 javascript()->CallConstruct(args->length() + 2, feedback);
2544 Node* value = ProcessArguments(call, args->length() + 2);
2545 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002546 ast_context()->ProduceValue(value);
2547}
2548
2549
2550void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002551 // The callee and the receiver both have to be pushed onto the operand stack
2552 // before arguments are being evaluated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002553 Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2554 Node* receiver_value = jsgraph()->UndefinedConstant();
2555
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556 environment()->Push(callee_value);
2557 environment()->Push(receiver_value);
2558
2559 // Evaluate all arguments to the JS runtime call.
2560 ZoneList<Expression*>* args = expr->arguments();
2561 VisitForValues(args);
2562
2563 // Create node to perform the JS runtime call.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002564 const Operator* call = javascript()->CallFunction(args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002565 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002566 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002567 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002568 ast_context()->ProduceValue(value);
2569}
2570
2571
2572void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002573 // Handle calls to runtime functions implemented in JavaScript separately as
2574 // the call follows JavaScript ABI and the callee is statically unknown.
2575 if (expr->is_jsruntime()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002576 return VisitCallJSRuntime(expr);
2577 }
2578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002579 const Runtime::Function* function = expr->function();
2580
2581 // TODO(mstarzinger): This bailout is a gigantic hack, the owner is ashamed.
2582 if (function->function_id == Runtime::kInlineGeneratorNext ||
Ben Murdoch097c5b22016-05-18 11:27:45 +01002583 function->function_id == Runtime::kInlineGeneratorReturn ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002584 function->function_id == Runtime::kInlineGeneratorThrow) {
2585 ast_context()->ProduceValue(jsgraph()->TheHoleConstant());
2586 return SetStackOverflow();
2587 }
2588
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002589 // Evaluate all arguments to the runtime call.
2590 ZoneList<Expression*>* args = expr->arguments();
2591 VisitForValues(args);
2592
2593 // Create node to perform the runtime call.
2594 Runtime::FunctionId functionId = function->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002595 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002596 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002597 Node* value = ProcessArguments(call, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002599 ast_context()->ProduceValue(value);
2600}
2601
2602
2603void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2604 switch (expr->op()) {
2605 case Token::DELETE:
2606 return VisitDelete(expr);
2607 case Token::VOID:
2608 return VisitVoid(expr);
2609 case Token::TYPEOF:
2610 return VisitTypeof(expr);
2611 case Token::NOT:
2612 return VisitNot(expr);
2613 default:
2614 UNREACHABLE();
2615 }
2616}
2617
2618
2619void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002620 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002621
2622 // Left-hand side can only be a property, a global or a variable slot.
2623 Property* property = expr->expression()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002624 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002625
2626 // Reserve space for result of postfix operation.
2627 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002628 if (is_postfix && assign_type != VARIABLE) {
2629 environment()->Push(jsgraph()->ZeroConstant());
2630 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002631
2632 // Evaluate LHS expression and get old value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002633 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002634 int stack_depth = -1;
2635 switch (assign_type) {
2636 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002637 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2638 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002639 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002640 old_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002641 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2642 pair, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002643 stack_depth = 0;
2644 break;
2645 }
2646 case NAMED_PROPERTY: {
2647 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002648 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002649 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002650 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002651 VectorSlotPair pair =
2652 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002653 old_value = BuildNamedLoad(object, name, pair);
2654 states.AddToNode(old_value, property->LoadId(),
2655 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002656 stack_depth = 1;
2657 break;
2658 }
2659 case KEYED_PROPERTY: {
2660 VisitForValue(property->obj());
2661 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002662 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002663 Node* key = environment()->Top();
2664 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002665 VectorSlotPair pair =
2666 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002667 old_value = BuildKeyedLoad(object, key, pair);
2668 states.AddToNode(old_value, property->LoadId(),
2669 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002670 stack_depth = 2;
2671 break;
2672 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002673 case NAMED_SUPER_PROPERTY: {
2674 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2675 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2676 FrameStateBeforeAndAfter states(this, property->obj()->id());
2677 Node* home_object = environment()->Top();
2678 Node* receiver = environment()->Peek(1);
2679 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2680 VectorSlotPair pair =
2681 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2682 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2683 states.AddToNode(old_value, property->LoadId(),
2684 OutputFrameStateCombine::Push());
2685 stack_depth = 2;
2686 break;
2687 }
2688 case KEYED_SUPER_PROPERTY: {
2689 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2690 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2691 VisitForValue(property->key());
2692 FrameStateBeforeAndAfter states(this, property->obj()->id());
2693 Node* key = environment()->Top();
2694 Node* home_object = environment()->Peek(1);
2695 Node* receiver = environment()->Peek(2);
2696 VectorSlotPair pair =
2697 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2698 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2699 states.AddToNode(old_value, property->LoadId(),
2700 OutputFrameStateCombine::Push());
2701 stack_depth = 3;
2702 break;
2703 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002704 }
2705
2706 // Convert old value into a number.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002707 if (!is_strong(language_mode())) {
2708 old_value = NewNode(javascript()->ToNumber(), old_value);
2709 PrepareFrameState(old_value, expr->ToNumberId(),
2710 OutputFrameStateCombine::Push());
2711 }
2712
2713 // Create a proper eager frame state for the stores.
2714 environment()->Push(old_value);
2715 FrameStateBeforeAndAfter store_states(this, expr->ToNumberId());
2716 old_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002717
2718 // Save result for postfix expressions at correct stack depth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002719 if (is_postfix) {
2720 if (assign_type != VARIABLE) {
2721 environment()->Poke(stack_depth, old_value);
2722 } else {
2723 environment()->Push(old_value);
2724 }
2725 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002726
2727 // Create node to perform +1/-1 operation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002728 Node* value;
2729 {
2730 // TODO(bmeurer): Cleanup this feedback/bailout mess!
2731 FrameStateBeforeAndAfter states(this, BailoutId::None());
2732 value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002733 expr->binary_op(), expr->CountBinOpFeedbackId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734 // This should never deoptimize outside strong mode because otherwise we
2735 // have converted to number before.
2736 states.AddToNode(value, is_strong(language_mode()) ? expr->ToNumberId()
2737 : BailoutId::None(),
2738 OutputFrameStateCombine::Ignore());
2739 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002740
2741 // Store the value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002742 VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002743 switch (assign_type) {
2744 case VARIABLE: {
2745 Variable* variable = expr->expression()->AsVariableProxy()->var();
2746 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002747 BuildVariableAssignment(variable, value, expr->op(), feedback,
2748 expr->AssignmentId(), store_states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002749 environment()->Pop();
2750 break;
2751 }
2752 case NAMED_PROPERTY: {
2753 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002754 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2755 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002756 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 store_states.AddToNode(store, expr->AssignmentId(),
2758 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002759 environment()->Pop();
2760 break;
2761 }
2762 case KEYED_PROPERTY: {
2763 Node* key = environment()->Pop();
2764 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002765 Node* store = BuildKeyedStore(object, key, 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());
2769 environment()->Pop();
2770 break;
2771 }
2772 case NAMED_SUPER_PROPERTY: {
2773 Node* home_object = environment()->Pop();
2774 Node* receiver = environment()->Pop();
2775 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2776 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2777 environment()->Push(value);
2778 store_states.AddToNode(store, expr->AssignmentId(),
2779 OutputFrameStateCombine::Ignore());
2780 environment()->Pop();
2781 break;
2782 }
2783 case KEYED_SUPER_PROPERTY: {
2784 Node* key = environment()->Pop();
2785 Node* home_object = environment()->Pop();
2786 Node* receiver = environment()->Pop();
2787 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2788 environment()->Push(value);
2789 store_states.AddToNode(store, expr->AssignmentId(),
2790 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002791 environment()->Pop();
2792 break;
2793 }
2794 }
2795
2796 // Restore old value for postfix expressions.
2797 if (is_postfix) value = environment()->Pop();
2798
2799 ast_context()->ProduceValue(value);
2800}
2801
2802
2803void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2804 switch (expr->op()) {
2805 case Token::COMMA:
2806 return VisitComma(expr);
2807 case Token::OR:
2808 case Token::AND:
2809 return VisitLogicalExpression(expr);
2810 default: {
2811 VisitForValue(expr->left());
2812 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002813 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002814 Node* right = environment()->Pop();
2815 Node* left = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002816 Node* value = BuildBinaryOp(left, right, expr->op(),
2817 expr->BinaryOperationFeedbackId());
2818 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002819 ast_context()->ProduceValue(value);
2820 }
2821 }
2822}
2823
2824
2825void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2826 const Operator* op;
2827 switch (expr->op()) {
2828 case Token::EQ:
2829 op = javascript()->Equal();
2830 break;
2831 case Token::NE:
2832 op = javascript()->NotEqual();
2833 break;
2834 case Token::EQ_STRICT:
2835 op = javascript()->StrictEqual();
2836 break;
2837 case Token::NE_STRICT:
2838 op = javascript()->StrictNotEqual();
2839 break;
2840 case Token::LT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002841 op = javascript()->LessThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002842 break;
2843 case Token::GT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002844 op = javascript()->GreaterThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002845 break;
2846 case Token::LTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002847 op = javascript()->LessThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002848 break;
2849 case Token::GTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002850 op = javascript()->GreaterThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002851 break;
2852 case Token::INSTANCEOF:
2853 op = javascript()->InstanceOf();
2854 break;
2855 case Token::IN:
2856 op = javascript()->HasProperty();
2857 break;
2858 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002859 op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002860 UNREACHABLE();
2861 }
2862 VisitForValue(expr->left());
2863 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002864 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002865 Node* right = environment()->Pop();
2866 Node* left = environment()->Pop();
2867 Node* value = NewNode(op, left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002868 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002869 ast_context()->ProduceValue(value);
2870}
2871
2872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002873void AstGraphBuilder::VisitSpread(Spread* expr) {
2874 // Handled entirely by the parser itself.
2875 UNREACHABLE();
2876}
2877
2878
2879void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2880 // Handled entirely by the parser itself.
2881 UNREACHABLE();
2882}
2883
2884
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002885void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2886 Node* value = GetFunctionClosure();
2887 ast_context()->ProduceValue(value);
2888}
2889
2890
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002891void AstGraphBuilder::VisitSuperPropertyReference(
2892 SuperPropertyReference* expr) {
2893 Node* value = BuildThrowUnsupportedSuperError(expr->id());
2894 ast_context()->ProduceValue(value);
2895}
2896
2897
2898void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2899 // Handled by VisitCall
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002900 UNREACHABLE();
2901}
2902
2903
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002904void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2905 // Handled entirely in VisitSwitch.
2906 UNREACHABLE();
2907}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002908
2909
2910void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002911 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002912 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002913 if (globals()->empty()) return;
2914 int array_index = 0;
2915 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2916 static_cast<int>(globals()->size()), TENURED);
2917 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002918 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
2919 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002920 DeclareGlobalsLanguageMode::encode(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002921 Node* flags = jsgraph()->Constant(encoded_flags);
2922 Node* pairs = jsgraph()->Constant(data);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002923 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002924 Node* call = NewNode(op, pairs, flags);
2925 PrepareFrameState(call, BailoutId::Declarations());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002926 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002927}
2928
2929
2930void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002931 if (stmt == nullptr) return;
2932 Visit(stmt);
2933}
2934
2935
2936void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2937 ContextScope scope(this, s, context);
2938 DCHECK(s->declarations()->is_empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002939 Visit(stmt);
2940}
2941
2942
2943void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002944 LoopBuilder* loop) {
2945 ControlScopeForIteration scope(this, stmt, loop);
2946 if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
2947 Node* node = NewNode(javascript()->StackCheck());
2948 PrepareFrameState(node, stmt->StackCheckId());
2949 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002950 Visit(stmt->body());
2951}
2952
2953
2954void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2955 Node* value;
2956 if (expr->expression()->IsVariableProxy()) {
2957 // Delete of an unqualified identifier is only allowed in classic mode but
2958 // deleting "this" is allowed in all language modes.
2959 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002960 // Delete of an unqualified identifier is disallowed in strict mode but
2961 // "delete this" is allowed.
2962 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002963 value = BuildVariableDelete(variable, expr->id(),
2964 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002965 } else if (expr->expression()->IsProperty()) {
2966 Property* property = expr->expression()->AsProperty();
2967 VisitForValue(property->obj());
2968 VisitForValue(property->key());
2969 Node* key = environment()->Pop();
2970 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002971 value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002972 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973 } else {
2974 VisitForEffect(expr->expression());
2975 value = jsgraph()->TrueConstant();
2976 }
2977 ast_context()->ProduceValue(value);
2978}
2979
2980
2981void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
2982 VisitForEffect(expr->expression());
2983 Node* value = jsgraph()->UndefinedConstant();
2984 ast_context()->ProduceValue(value);
2985}
2986
2987
2988void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
2989 Node* operand;
2990 if (expr->expression()->IsVariableProxy()) {
2991 // Typeof does not throw a reference error on global variables, hence we
2992 // perform a non-contextual load in case the operand is a variable proxy.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002993 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2994 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002995 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2996 operand =
2997 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, pair,
2998 OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002999 } else {
3000 VisitForValue(expr->expression());
3001 operand = environment()->Pop();
3002 }
3003 Node* value = NewNode(javascript()->TypeOf(), operand);
3004 ast_context()->ProduceValue(value);
3005}
3006
3007
3008void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3009 VisitForValue(expr->expression());
3010 Node* operand = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003011 Node* input = BuildToBoolean(operand, expr->expression()->test_id());
3012 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
3013 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003014 ast_context()->ProduceValue(value);
3015}
3016
3017
3018void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3019 VisitForEffect(expr->left());
3020 Visit(expr->right());
3021 ast_context()->ReplaceValue();
3022}
3023
3024
3025void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3026 bool is_logical_and = expr->op() == Token::AND;
3027 IfBuilder compare_if(this);
3028 VisitForValue(expr->left());
3029 Node* condition = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003030 compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003031 compare_if.Then();
3032 if (is_logical_and) {
3033 environment()->Pop();
3034 Visit(expr->right());
3035 } else if (ast_context()->IsEffect()) {
3036 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003037 } else if (ast_context()->IsTest()) {
3038 environment()->Poke(0, jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003039 }
3040 compare_if.Else();
3041 if (!is_logical_and) {
3042 environment()->Pop();
3043 Visit(expr->right());
3044 } else if (ast_context()->IsEffect()) {
3045 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003046 } else if (ast_context()->IsTest()) {
3047 environment()->Poke(0, jsgraph()->FalseConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003048 }
3049 compare_if.End();
3050 ast_context()->ReplaceValue();
3051}
3052
3053
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003054LanguageMode AstGraphBuilder::language_mode() const {
3055 return info()->language_mode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003056}
3057
3058
3059VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003060 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003061 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3062}
3063
3064
Ben Murdoch097c5b22016-05-18 11:27:45 +01003065void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003066 Visit(node->expression());
3067}
3068
3069
3070namespace {
3071
3072// Limit of context chain length to which inline check is possible.
3073const int kMaxCheckDepth = 30;
3074
3075// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3076const uint32_t kFullCheckRequired = -1;
3077
3078} // namespace
3079
3080
3081uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3082 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3083 bool found_eval_scope = false;
3084 uint32_t check_depths = 0;
3085 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3086 if (s->num_heap_slots() <= 0) continue;
3087 // TODO(mstarzinger): If we have reached an eval scope, we check all
3088 // extensions from this point. Replicated from full-codegen, figure out
3089 // whether this is still needed. If not, drop {found_eval_scope} below.
3090 if (s->is_eval_scope()) found_eval_scope = true;
3091 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3092 int depth = current_scope()->ContextChainLength(s);
3093 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3094 check_depths |= 1 << depth;
3095 }
3096 return check_depths;
3097}
3098
3099
3100uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3101 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3102 uint32_t check_depths = 0;
3103 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3104 if (s->num_heap_slots() <= 0) continue;
3105 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3106 int depth = current_scope()->ContextChainLength(s);
3107 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3108 check_depths |= 1 << depth;
3109 if (s == variable->scope()) break;
3110 }
3111 return check_depths;
3112}
3113
3114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003115Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3116 DCHECK(environment()->stack_height() >= arity);
3117 Node** all = info()->zone()->NewArray<Node*>(arity);
3118 for (int i = arity - 1; i >= 0; --i) {
3119 all[i] = environment()->Pop();
3120 }
3121 Node* value = NewNode(op, arity, all);
3122 return value;
3123}
3124
3125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003126Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3127 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003128
3129 // Allocate a new local context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003130 Node* local_context = scope->is_script_scope()
3131 ? BuildLocalScriptContext(scope)
3132 : BuildLocalFunctionContext(scope);
3133
3134 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3135 Node* receiver = environment()->RawParameterLookup(0);
3136 // Context variable (at bottom of the context chain).
3137 Variable* variable = scope->receiver();
3138 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3139 const Operator* op = javascript()->StoreContext(0, variable->index());
3140 NewNode(op, local_context, receiver);
3141 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003142
3143 // Copy parameters into context if necessary.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003144 int num_parameters = scope->num_parameters();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003145 for (int i = 0; i < num_parameters; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003146 Variable* variable = scope->parameter(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003147 if (!variable->IsContextSlot()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003148 Node* parameter = environment()->RawParameterLookup(i + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003149 // Context variable (at bottom of the context chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003150 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003151 const Operator* op = javascript()->StoreContext(0, variable->index());
3152 NewNode(op, local_context, parameter);
3153 }
3154
3155 return local_context;
3156}
3157
3158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003159Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
3160 DCHECK(scope->is_function_scope());
3161
3162 // Allocate a new local context.
3163 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3164 const Operator* op = javascript()->CreateFunctionContext(slot_count);
3165 Node* local_context = NewNode(op, GetFunctionClosure());
3166
3167 return local_context;
3168}
3169
3170
3171Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3172 DCHECK(scope->is_script_scope());
3173
3174 // Allocate a new local context.
3175 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3176 const Operator* op = javascript()->CreateScriptContext(scope_info);
3177 Node* local_context = NewNode(op, GetFunctionClosure());
3178 PrepareFrameState(local_context, BailoutId::ScriptContext(),
3179 OutputFrameStateCombine::Push());
3180
3181 return local_context;
3182}
3183
3184
3185Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3186 DCHECK(scope->is_block_scope());
3187
3188 // Allocate a new local context.
3189 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3190 const Operator* op = javascript()->CreateBlockContext(scope_info);
3191 Node* local_context = NewNode(op, GetFunctionClosureForContext());
3192
3193 return local_context;
3194}
3195
3196
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003197Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003198 if (arguments == nullptr) return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003199
3200 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003201 CreateArgumentsType type =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003202 is_strict(language_mode()) || !info()->has_simple_parameters()
Ben Murdoch097c5b22016-05-18 11:27:45 +01003203 ? CreateArgumentsType::kUnmappedArguments
3204 : CreateArgumentsType::kMappedArguments;
3205 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003206 Node* object = NewNode(op, GetFunctionClosure());
3207 PrepareFrameState(object, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003209 // Assign the object to the {arguments} variable. This should never lazy
3210 // deopt, so it is fine to send invalid bailout id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003211 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003212 FrameStateBeforeAndAfter states(this, BailoutId::None());
3213 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3214 BailoutId::None(), states);
3215 return object;
3216}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003217
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003218
3219Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3220 if (rest == nullptr) return nullptr;
3221
3222 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003223 CreateArgumentsType type = CreateArgumentsType::kRestParameter;
3224 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003225 Node* object = NewNode(op, GetFunctionClosure());
3226 PrepareFrameState(object, BailoutId::None());
3227
3228 // Assign the object to the {rest} variable. This should never lazy
3229 // deopt, so it is fine to send invalid bailout id.
3230 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3231 FrameStateBeforeAndAfter states(this, BailoutId::None());
3232 BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3233 BailoutId::None(), states);
3234 return object;
3235}
3236
3237
3238Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3239 if (this_function_var == nullptr) return nullptr;
3240
3241 // Retrieve the closure we were called with.
3242 Node* this_function = GetFunctionClosure();
3243
3244 // Assign the object to the {.this_function} variable. This should never lazy
3245 // deopt, so it is fine to send invalid bailout id.
3246 FrameStateBeforeAndAfter states(this, BailoutId::None());
3247 BuildVariableAssignment(this_function_var, this_function, Token::INIT,
3248 VectorSlotPair(), BailoutId::None(), states);
3249 return this_function;
3250}
3251
3252
3253Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3254 if (new_target_var == nullptr) return nullptr;
3255
3256 // Retrieve the new target we were called with.
3257 Node* object = GetNewTarget();
3258
3259 // Assign the object to the {new.target} variable. This should never lazy
3260 // deopt, so it is fine to send invalid bailout id.
3261 FrameStateBeforeAndAfter states(this, BailoutId::None());
3262 BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
3263 BailoutId::None(), states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003264 return object;
3265}
3266
3267
3268Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
3269 Node* not_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003270 Node* the_hole = jsgraph()->TheHoleConstant();
3271 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3272 return NewNode(
3273 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
3274 check, for_hole, not_hole);
3275}
3276
3277
3278Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3279 Node* not_hole,
3280 BailoutId bailout_id) {
3281 IfBuilder hole_check(this);
3282 Node* the_hole = jsgraph()->TheHoleConstant();
3283 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3284 hole_check.If(check);
3285 hole_check.Then();
3286 Node* error = BuildThrowReferenceError(variable, bailout_id);
3287 environment()->Push(error);
3288 hole_check.Else();
3289 environment()->Push(not_hole);
3290 hole_check.End();
3291 return environment()->Pop();
3292}
3293
3294
3295Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3296 Node* for_hole,
3297 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003298 IfBuilder hole_check(this);
3299 Node* the_hole = jsgraph()->TheHoleConstant();
3300 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3301 hole_check.If(check);
3302 hole_check.Then();
3303 environment()->Push(for_hole);
3304 hole_check.Else();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003305 Node* error = BuildThrowReferenceError(variable, bailout_id);
3306 environment()->Push(error);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003307 hole_check.End();
3308 return environment()->Pop();
3309}
3310
3311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003312Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3313 BailoutId bailout_id) {
3314 IfBuilder prototype_check(this);
3315 Node* prototype_string =
3316 jsgraph()->Constant(isolate()->factory()->prototype_string());
3317 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
3318 prototype_check.If(check);
3319 prototype_check.Then();
3320 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3321 environment()->Push(error);
3322 prototype_check.Else();
3323 environment()->Push(name);
3324 prototype_check.End();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003325 return environment()->Pop();
3326}
3327
3328
3329Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3330 BailoutId bailout_id,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003331 FrameStateBeforeAndAfter& states,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003332 const VectorSlotPair& feedback,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003333 OutputFrameStateCombine combine,
3334 TypeofMode typeof_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003335 Node* the_hole = jsgraph()->TheHoleConstant();
3336 VariableMode mode = variable->mode();
3337 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003338 case VariableLocation::GLOBAL:
3339 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003340 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003341 Handle<Name> name = variable->name();
3342 if (Node* node = TryLoadGlobalConstant(name)) return node;
3343 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
3344 states.AddToNode(value, bailout_id, combine);
3345 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003346 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003347 case VariableLocation::PARAMETER:
3348 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003349 // Local var, const, or let variable.
3350 Node* value = environment()->Lookup(variable);
3351 if (mode == CONST_LEGACY) {
3352 // Perform check for uninitialized legacy const variables.
3353 if (value->op() == the_hole->op()) {
3354 value = jsgraph()->UndefinedConstant();
3355 } else if (value->opcode() == IrOpcode::kPhi) {
3356 Node* undefined = jsgraph()->UndefinedConstant();
3357 value = BuildHoleCheckSilent(value, undefined, value);
3358 }
3359 } else if (mode == LET || mode == CONST) {
3360 // Perform check for uninitialized let/const variables.
3361 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003362 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003363 } else if (value->opcode() == IrOpcode::kPhi) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003364 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003365 }
3366 }
3367 return value;
3368 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003369 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003370 // Context variable (potentially up the context chain).
3371 int depth = current_scope()->ContextChainLength(variable->scope());
3372 bool immutable = variable->maybe_assigned() == kNotAssigned;
3373 const Operator* op =
3374 javascript()->LoadContext(depth, variable->index(), immutable);
3375 Node* value = NewNode(op, current_context());
3376 // TODO(titzer): initialization checks are redundant for already
3377 // initialized immutable context loads, but only specialization knows.
3378 // Maybe specializer should be a parameter to the graph builder?
3379 if (mode == CONST_LEGACY) {
3380 // Perform check for uninitialized legacy const variables.
3381 Node* undefined = jsgraph()->UndefinedConstant();
3382 value = BuildHoleCheckSilent(value, undefined, value);
3383 } else if (mode == LET || mode == CONST) {
3384 // Perform check for uninitialized let/const variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003385 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003386 }
3387 return value;
3388 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003389 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003390 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003391 Handle<String> name = variable->name();
3392 if (Node* node =
3393 TryLoadDynamicVariable(variable, name, bailout_id, states,
3394 feedback, combine, typeof_mode)) {
3395 return node;
3396 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003397 Node* value = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003398 states.AddToNode(value, bailout_id, combine);
3399 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003400 }
3401 }
3402 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003403 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003404}
3405
3406
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003407Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3408 BailoutId bailout_id,
3409 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003410 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003411 case VariableLocation::GLOBAL:
3412 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003413 // Global var, const, or let variable.
3414 Node* global = BuildLoadGlobalObject();
3415 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003416 const Operator* op = javascript()->DeleteProperty(language_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003417 Node* result = NewNode(op, global, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003418 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003419 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003420 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003421 case VariableLocation::PARAMETER:
3422 case VariableLocation::LOCAL:
3423 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003424 // Local var, const, or let variable or context variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003425 return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3426 }
3427 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003428 // Dynamic lookup of context variable (anywhere in the chain).
3429 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003430 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003431 javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
3432 Node* result = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003433 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003434 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003435 }
3436 }
3437 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003438 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003439}
3440
3441
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003442Node* AstGraphBuilder::BuildVariableAssignment(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003443 Variable* variable, Node* value, Token::Value op,
3444 const VectorSlotPair& feedback, BailoutId bailout_id,
3445 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003446 Node* the_hole = jsgraph()->TheHoleConstant();
3447 VariableMode mode = variable->mode();
3448 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003449 case VariableLocation::GLOBAL:
3450 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003451 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003452 Handle<Name> name = variable->name();
3453 Node* store = BuildGlobalStore(name, value, feedback);
3454 states.AddToNode(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003455 return store;
3456 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003457 case VariableLocation::PARAMETER:
3458 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003459 // Local var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003460 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003461 // Perform an initialization check for legacy const variables.
3462 Node* current = environment()->Lookup(variable);
3463 if (current->op() != the_hole->op()) {
3464 value = BuildHoleCheckSilent(current, value, current);
3465 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003466 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3467 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003468 // - exception in strict mode.
3469 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003470 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003471 return BuildThrowConstAssignError(bailout_id);
3472 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003473 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003474 } else if (mode == LET && op == Token::INIT) {
3475 // No initialization check needed because scoping guarantees it. Note
3476 // that we still perform a lookup to keep the variable live, because
3477 // baseline code might contain debug code that inspects the variable.
3478 Node* current = environment()->Lookup(variable);
3479 CHECK_NOT_NULL(current);
3480 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003481 // Perform an initialization check for let declared variables.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003482 Node* current = environment()->Lookup(variable);
3483 if (current->op() == the_hole->op()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003484 return BuildThrowReferenceError(variable, bailout_id);
3485 } else if (current->opcode() == IrOpcode::kPhi) {
3486 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003487 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003488 } else if (mode == CONST && op == Token::INIT) {
3489 // Perform an initialization check for const {this} variables.
3490 // Note that the {this} variable is the only const variable being able
3491 // to trigger bind operations outside the TDZ, via {super} calls.
3492 Node* current = environment()->Lookup(variable);
3493 if (current->op() != the_hole->op() && variable->is_this()) {
3494 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3495 }
3496 } else if (mode == CONST && op != Token::INIT) {
3497 // Assignment to const is exception in all modes.
3498 Node* current = environment()->Lookup(variable);
3499 if (current->op() == the_hole->op()) {
3500 return BuildThrowReferenceError(variable, bailout_id);
3501 } else if (current->opcode() == IrOpcode::kPhi) {
3502 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3503 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003504 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003505 }
3506 environment()->Bind(variable, value);
3507 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003508 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003509 // Context variable (potentially up the context chain).
3510 int depth = current_scope()->ContextChainLength(variable->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003511 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003512 // Perform an initialization check for legacy const variables.
3513 const Operator* op =
3514 javascript()->LoadContext(depth, variable->index(), false);
3515 Node* current = NewNode(op, current_context());
3516 value = BuildHoleCheckSilent(current, value, current);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003517 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3518 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003519 // - exception in strict mode.
3520 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003521 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003522 return BuildThrowConstAssignError(bailout_id);
3523 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003524 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003525 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003526 // Perform an initialization check for let declared variables.
3527 const Operator* op =
3528 javascript()->LoadContext(depth, variable->index(), false);
3529 Node* current = NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003530 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3531 } else if (mode == CONST && op == Token::INIT) {
3532 // Perform an initialization check for const {this} variables.
3533 // Note that the {this} variable is the only const variable being able
3534 // to trigger bind operations outside the TDZ, via {super} calls.
3535 if (variable->is_this()) {
3536 const Operator* op =
3537 javascript()->LoadContext(depth, variable->index(), false);
3538 Node* current = NewNode(op, current_context());
3539 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3540 }
3541 } else if (mode == CONST && op != Token::INIT) {
3542 // Assignment to const is exception in all modes.
3543 const Operator* op =
3544 javascript()->LoadContext(depth, variable->index(), false);
3545 Node* current = NewNode(op, current_context());
3546 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003547 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003548 }
3549 const Operator* op = javascript()->StoreContext(depth, variable->index());
3550 return NewNode(op, current_context(), value);
3551 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003552 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003553 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch097c5b22016-05-18 11:27:45 +01003554 Handle<Name> name = variable->name();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003555 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
3556 // initializations of const declarations.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003557 Node* store = BuildDynamicStore(name, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003558 PrepareFrameState(store, bailout_id, combine);
3559 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003560 }
3561 }
3562 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003563 return nullptr;
3564}
3565
3566
3567Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3568 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003569 const Operator* op = javascript()->LoadProperty(feedback);
3570 Node* node = NewNode(op, object, key, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003571 return node;
3572}
3573
3574
3575Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3576 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003577 const Operator* op = javascript()->LoadNamed(name, feedback);
3578 Node* node = NewNode(op, object, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003579 return node;
3580}
3581
3582
3583Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3584 const VectorSlotPair& feedback) {
3585 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003586 Node* node = NewNode(op, object, key, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003587 return node;
3588}
3589
3590
3591Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3592 Node* value,
3593 const VectorSlotPair& feedback) {
3594 const Operator* op =
3595 javascript()->StoreNamed(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003596 Node* node = NewNode(op, object, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003597 return node;
3598}
3599
3600
3601Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3602 Handle<Name> name,
3603 const VectorSlotPair& feedback) {
3604 Node* name_node = jsgraph()->Constant(name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003605 const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
3606 Node* node = NewNode(op, receiver, home_object, name_node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003607 return node;
3608}
3609
3610
3611Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3612 Node* key,
3613 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003614 const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
3615 Node* node = NewNode(op, receiver, home_object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003616 return node;
3617}
3618
3619
3620Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3621 Node* key, Node* value) {
3622 Runtime::FunctionId function_id = is_strict(language_mode())
3623 ? Runtime::kStoreKeyedToSuper_Strict
3624 : Runtime::kStoreKeyedToSuper_Sloppy;
3625 const Operator* op = javascript()->CallRuntime(function_id, 4);
3626 Node* node = NewNode(op, receiver, home_object, key, value);
3627 return node;
3628}
3629
3630
3631Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3632 Handle<Name> name, Node* value) {
3633 Node* name_node = jsgraph()->Constant(name);
3634 Runtime::FunctionId function_id = is_strict(language_mode())
3635 ? Runtime::kStoreToSuper_Strict
3636 : Runtime::kStoreToSuper_Sloppy;
3637 const Operator* op = javascript()->CallRuntime(function_id, 4);
3638 Node* node = NewNode(op, receiver, home_object, name_node, value);
3639 return node;
3640}
3641
3642
3643Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3644 const VectorSlotPair& feedback,
3645 TypeofMode typeof_mode) {
3646 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003647 Node* node = NewNode(op, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003648 return node;
3649}
3650
3651
3652Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3653 const VectorSlotPair& feedback) {
3654 const Operator* op =
3655 javascript()->StoreGlobal(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003656 Node* node = NewNode(op, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003657 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003658}
3659
3660
Ben Murdoch097c5b22016-05-18 11:27:45 +01003661Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
3662 TypeofMode typeof_mode) {
3663 Node* name_node = jsgraph()->Constant(name);
3664 const Operator* op =
3665 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
3666 ? Runtime::kLoadLookupSlot
3667 : Runtime::kLoadLookupSlotInsideTypeof);
3668 Node* node = NewNode(op, name_node);
3669 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003670}
3671
3672
Ben Murdoch097c5b22016-05-18 11:27:45 +01003673Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
3674 Node* name_node = jsgraph()->Constant(name);
3675 const Operator* op = javascript()->CallRuntime(
3676 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
3677 : Runtime::kStoreLookupSlot_Sloppy);
3678 Node* node = NewNode(op, name_node, value);
3679 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003680}
3681
3682
3683Node* AstGraphBuilder::BuildLoadGlobalObject() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003684 return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003685}
3686
3687
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003688Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3689 const Operator* op =
3690 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3691 Node* native_context = NewNode(op, current_context());
3692 return NewNode(javascript()->LoadContext(0, index, true), native_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003693}
3694
3695
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003696Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3697 if (Node* node = TryFastToBoolean(input)) return node;
3698 ToBooleanHints hints;
3699 if (!type_hint_analysis_ ||
3700 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3701 hints = ToBooleanHint::kAny;
3702 }
3703 return NewNode(javascript()->ToBoolean(hints), input);
3704}
3705
3706
3707Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3708 if (Node* node = TryFastToName(input)) return node;
3709 Node* name = NewNode(javascript()->ToName(), input);
3710 PrepareFrameState(name, bailout_id);
3711 return name;
3712}
3713
3714
3715Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3716 Node* object = NewNode(javascript()->ToObject(), input);
3717 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3718 return object;
3719}
3720
3721
3722Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3723 ObjectLiteralProperty* property,
3724 int slot_number) {
3725 Expression* expr = property->value();
3726 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3727 Handle<Name> name = isolate()->factory()->home_object_symbol();
3728 FrameStateBeforeAndAfter states(this, BailoutId::None());
3729 VectorSlotPair feedback =
3730 CreateVectorSlotPair(property->GetSlot(slot_number));
3731 Node* store = BuildNamedStore(value, name, home_object, feedback);
3732 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3733 return store;
3734}
3735
3736
3737Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003738 const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003739 Node* call = NewNode(op, exception);
3740 PrepareFrameState(call, bailout_id);
3741 Node* control = NewNode(common()->Throw(), call);
3742 UpdateControlDependencyToLeaveFunction(control);
3743 return call;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003744}
3745
3746
3747Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3748 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003749 Node* variable_name = jsgraph()->Constant(variable->name());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003750 const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003751 Node* call = NewNode(op, variable_name);
3752 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003753 Node* control = NewNode(common()->Throw(), call);
3754 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003755 return call;
3756}
3757
3758
3759Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003760 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003761 javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003762 Node* call = NewNode(op);
3763 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003764 Node* control = NewNode(common()->Throw(), call);
3765 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003766 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003767}
3768
3769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003770Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3771 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003772 javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003773 Node* call = NewNode(op);
3774 PrepareFrameState(call, bailout_id);
3775 Node* control = NewNode(common()->Throw(), call);
3776 UpdateControlDependencyToLeaveFunction(control);
3777 return call;
3778}
3779
3780
3781Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3782 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003783 javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003784 Node* call = NewNode(op);
3785 PrepareFrameState(call, bailout_id);
3786 Node* control = NewNode(common()->Throw(), call);
3787 UpdateControlDependencyToLeaveFunction(control);
3788 return call;
3789}
3790
3791
3792Node* AstGraphBuilder::BuildReturn(Node* return_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003793 // Emit tracing call if requested to do so.
3794 if (FLAG_trace) {
3795 return_value =
3796 NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
3797 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003798 Node* control = NewNode(common()->Return(), return_value);
3799 UpdateControlDependencyToLeaveFunction(control);
3800 return control;
3801}
3802
3803
3804Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003805 NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003806 Node* control = NewNode(common()->Throw(), exception_value);
3807 UpdateControlDependencyToLeaveFunction(control);
3808 return control;
3809}
3810
3811
3812Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3813 TypeFeedbackId feedback_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003814 const Operator* js_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003815 BinaryOperationHints hints;
3816 if (!type_hint_analysis_ ||
3817 !type_hint_analysis_->GetBinaryOperationHints(feedback_id, &hints)) {
3818 hints = BinaryOperationHints::Any();
3819 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003820 switch (op) {
3821 case Token::BIT_OR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003822 js_op = javascript()->BitwiseOr(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003823 break;
3824 case Token::BIT_AND:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003825 js_op = javascript()->BitwiseAnd(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003826 break;
3827 case Token::BIT_XOR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003828 js_op = javascript()->BitwiseXor(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003829 break;
3830 case Token::SHL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003831 js_op = javascript()->ShiftLeft(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003832 break;
3833 case Token::SAR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003834 js_op = javascript()->ShiftRight(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003835 break;
3836 case Token::SHR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003837 js_op = javascript()->ShiftRightLogical(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003838 break;
3839 case Token::ADD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003840 js_op = javascript()->Add(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003841 break;
3842 case Token::SUB:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003843 js_op = javascript()->Subtract(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003844 break;
3845 case Token::MUL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003846 js_op = javascript()->Multiply(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003847 break;
3848 case Token::DIV:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003849 js_op = javascript()->Divide(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003850 break;
3851 case Token::MOD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003852 js_op = javascript()->Modulus(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003853 break;
3854 default:
3855 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003856 js_op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003857 }
3858 return NewNode(js_op, left, right);
3859}
3860
3861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003862Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3863 // Optimize global constants like "undefined", "Infinity", and "NaN".
3864 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3865 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3866 return nullptr;
3867}
3868
3869
3870Node* AstGraphBuilder::TryLoadDynamicVariable(
3871 Variable* variable, Handle<String> name, BailoutId bailout_id,
3872 FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
3873 OutputFrameStateCombine combine, TypeofMode typeof_mode) {
3874 VariableMode mode = variable->mode();
3875
3876 if (mode == DYNAMIC_GLOBAL) {
3877 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3878 if (bitset == kFullCheckRequired) return nullptr;
3879
3880 // We are using two blocks to model fast and slow cases.
3881 BlockBuilder fast_block(this);
3882 BlockBuilder slow_block(this);
3883 environment()->Push(jsgraph()->TheHoleConstant());
3884 slow_block.BeginBlock();
3885 environment()->Pop();
3886 fast_block.BeginBlock();
3887
3888 // Perform checks whether the fast mode applies, by looking for any
3889 // extension object which might shadow the optimistic declaration.
3890 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3891 if ((bitset & 1) == 0) continue;
3892 Node* load = NewNode(
3893 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3894 current_context());
3895 Node* check = NewNode(javascript()->StrictEqual(), load,
3896 jsgraph()->TheHoleConstant());
3897 fast_block.BreakUnless(check, BranchHint::kTrue);
3898 }
3899
Ben Murdoch097c5b22016-05-18 11:27:45 +01003900 // Fast case, because variable is not shadowed.
3901 if (Node* constant = TryLoadGlobalConstant(name)) {
3902 environment()->Push(constant);
3903 } else {
3904 // Perform global slot load.
3905 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3906 states.AddToNode(fast, bailout_id, combine);
3907 environment()->Push(fast);
3908 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003909 slow_block.Break();
3910 environment()->Pop();
3911 fast_block.EndBlock();
3912
3913 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003914 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003915 states.AddToNode(slow, bailout_id, combine);
3916 environment()->Push(slow);
3917 slow_block.EndBlock();
3918
3919 return environment()->Pop();
3920 }
3921
3922 if (mode == DYNAMIC_LOCAL) {
3923 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3924 if (bitset == kFullCheckRequired) return nullptr;
3925
3926 // We are using two blocks to model fast and slow cases.
3927 BlockBuilder fast_block(this);
3928 BlockBuilder slow_block(this);
3929 environment()->Push(jsgraph()->TheHoleConstant());
3930 slow_block.BeginBlock();
3931 environment()->Pop();
3932 fast_block.BeginBlock();
3933
3934 // Perform checks whether the fast mode applies, by looking for any
3935 // extension object which might shadow the optimistic declaration.
3936 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3937 if ((bitset & 1) == 0) continue;
3938 Node* load = NewNode(
3939 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3940 current_context());
3941 Node* check = NewNode(javascript()->StrictEqual(), load,
3942 jsgraph()->TheHoleConstant());
3943 fast_block.BreakUnless(check, BranchHint::kTrue);
3944 }
3945
3946 // Fast case, because variable is not shadowed. Perform context slot load.
3947 Variable* local = variable->local_if_not_shadowed();
3948 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3949 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3950 typeof_mode);
3951 environment()->Push(fast);
3952 slow_block.Break();
3953 environment()->Pop();
3954 fast_block.EndBlock();
3955
3956 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003957 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003958 states.AddToNode(slow, bailout_id, combine);
3959 environment()->Push(slow);
3960 slow_block.EndBlock();
3961
3962 return environment()->Pop();
3963 }
3964
3965 return nullptr;
3966}
3967
3968
3969Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3970 switch (input->opcode()) {
3971 case IrOpcode::kNumberConstant: {
3972 NumberMatcher m(input);
3973 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3974 }
3975 case IrOpcode::kHeapConstant: {
3976 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3977 return jsgraph_->BooleanConstant(object->BooleanValue());
3978 }
3979 case IrOpcode::kJSEqual:
3980 case IrOpcode::kJSNotEqual:
3981 case IrOpcode::kJSStrictEqual:
3982 case IrOpcode::kJSStrictNotEqual:
3983 case IrOpcode::kJSLessThan:
3984 case IrOpcode::kJSLessThanOrEqual:
3985 case IrOpcode::kJSGreaterThan:
3986 case IrOpcode::kJSGreaterThanOrEqual:
3987 case IrOpcode::kJSToBoolean:
3988 case IrOpcode::kJSDeleteProperty:
3989 case IrOpcode::kJSHasProperty:
3990 case IrOpcode::kJSInstanceOf:
3991 return input;
3992 default:
3993 break;
3994 }
3995 return nullptr;
3996}
3997
3998
3999Node* AstGraphBuilder::TryFastToName(Node* input) {
4000 switch (input->opcode()) {
4001 case IrOpcode::kHeapConstant: {
4002 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4003 if (object->IsName()) return input;
4004 break;
4005 }
4006 case IrOpcode::kJSToString:
4007 case IrOpcode::kJSToName:
4008 case IrOpcode::kJSTypeOf:
4009 return input;
4010 default:
4011 break;
4012 }
4013 return nullptr;
4014}
4015
4016
4017bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4018 if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4019 info()->set_osr_expr_stack_height(std::max(
4020 environment()->stack_height(), info()->osr_expr_stack_height()));
4021 return true;
4022 }
4023 return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004024}
4025
4026
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004027void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4028 OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004029 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4030 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4031
4032 DCHECK_EQ(IrOpcode::kDead,
4033 NodeProperties::GetFrameStateInput(node, 0)->opcode());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004034 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004035 NodeProperties::ReplaceFrameStateInput(
Ben Murdoch097c5b22016-05-18 11:27:45 +01004036 node, 0,
4037 environment()->Checkpoint(ast_id, combine, node_has_exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004038 }
4039}
4040
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004041
4042BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4043 IterationStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004044 if (loop_assignment_analysis_ == nullptr) return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004045 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004046}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004048
4049Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4050 if (size > input_buffer_size_) {
4051 size = size + kInputBufferSizeIncrement + input_buffer_size_;
4052 input_buffer_ = local_zone()->NewArray<Node*>(size);
4053 input_buffer_size_ = size;
4054 }
4055 return input_buffer_;
4056}
4057
4058
4059Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4060 Node** value_inputs, bool incomplete) {
4061 DCHECK_EQ(op->ValueInputCount(), value_input_count);
4062
4063 bool has_context = OperatorProperties::HasContextInput(op);
4064 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4065 bool has_control = op->ControlInputCount() == 1;
4066 bool has_effect = op->EffectInputCount() == 1;
4067
4068 DCHECK(op->ControlInputCount() < 2);
4069 DCHECK(op->EffectInputCount() < 2);
4070
4071 Node* result = nullptr;
4072 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4073 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4074 } else {
4075 bool inside_try_scope = try_nesting_level_ > 0;
4076 int input_count_with_deps = value_input_count;
4077 if (has_context) ++input_count_with_deps;
4078 input_count_with_deps += frame_state_count;
4079 if (has_control) ++input_count_with_deps;
4080 if (has_effect) ++input_count_with_deps;
4081 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4082 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4083 Node** current_input = buffer + value_input_count;
4084 if (has_context) {
4085 *current_input++ = current_context();
4086 }
4087 for (int i = 0; i < frame_state_count; i++) {
4088 // The frame state will be inserted later. Here we misuse
4089 // the {Dead} node as a sentinel to be later overwritten
4090 // with the real frame state.
4091 *current_input++ = jsgraph()->Dead();
4092 }
4093 if (has_effect) {
4094 *current_input++ = environment_->GetEffectDependency();
4095 }
4096 if (has_control) {
4097 *current_input++ = environment_->GetControlDependency();
4098 }
4099 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4100 if (!environment()->IsMarkedAsUnreachable()) {
4101 // Update the current control dependency for control-producing nodes.
4102 if (NodeProperties::IsControl(result)) {
4103 environment_->UpdateControlDependency(result);
4104 }
4105 // Update the current effect dependency for effect-producing nodes.
4106 if (result->op()->EffectOutputCount() > 0) {
4107 environment_->UpdateEffectDependency(result);
4108 }
4109 // Add implicit exception continuation for throwing nodes.
4110 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4111 // Conservative prediction whether caught locally.
4112 IfExceptionHint hint = try_catch_nesting_level_ > 0
4113 ? IfExceptionHint::kLocallyCaught
4114 : IfExceptionHint::kLocallyUncaught;
4115 // Copy the environment for the success continuation.
4116 Environment* success_env = environment()->CopyForConditional();
4117 const Operator* op = common()->IfException(hint);
4118 Node* effect = environment()->GetEffectDependency();
4119 Node* on_exception = graph()->NewNode(op, effect, result);
4120 environment_->UpdateControlDependency(on_exception);
4121 environment_->UpdateEffectDependency(on_exception);
4122 execution_control()->ThrowValue(on_exception);
4123 set_environment(success_env);
4124 }
4125 // Add implicit success continuation for throwing nodes.
4126 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4127 const Operator* op = common()->IfSuccess();
4128 Node* on_success = graph()->NewNode(op, result);
4129 environment_->UpdateControlDependency(on_success);
4130 }
4131 }
4132 }
4133
4134 return result;
4135}
4136
4137
4138void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4139 if (environment()->IsMarkedAsUnreachable()) return;
4140 environment()->MarkAsUnreachable();
4141 exit_controls_.push_back(exit);
4142}
4143
4144
4145void AstGraphBuilder::Environment::Merge(Environment* other) {
4146 DCHECK(values_.size() == other->values_.size());
4147 DCHECK(contexts_.size() == other->contexts_.size());
4148
4149 // Nothing to do if the other environment is dead.
4150 if (other->IsMarkedAsUnreachable()) return;
4151
4152 // Resurrect a dead environment by copying the contents of the other one and
4153 // placing a singleton merge as the new control dependency.
4154 if (this->IsMarkedAsUnreachable()) {
4155 Node* other_control = other->control_dependency_;
4156 Node* inputs[] = {other_control};
4157 control_dependency_ =
4158 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4159 effect_dependency_ = other->effect_dependency_;
4160 values_ = other->values_;
4161 contexts_ = other->contexts_;
4162 if (IsLivenessAnalysisEnabled()) {
4163 liveness_block_ =
4164 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4165 }
4166 return;
4167 }
4168
4169 // Record the merge for the local variable liveness calculation.
4170 // For loops, we are connecting a back edge into the existing block;
4171 // for merges, we create a new merged block.
4172 if (IsLivenessAnalysisEnabled()) {
4173 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4174 liveness_block_ =
4175 builder_->liveness_analyzer()->NewBlock(liveness_block());
4176 }
4177 liveness_block()->AddPredecessor(other->liveness_block());
4178 }
4179
4180 // Create a merge of the control dependencies of both environments and update
4181 // the current environment's control dependency accordingly.
4182 Node* control = builder_->MergeControl(this->GetControlDependency(),
4183 other->GetControlDependency());
4184 UpdateControlDependency(control);
4185
4186 // Create a merge of the effect dependencies of both environments and update
4187 // the current environment's effect dependency accordingly.
4188 Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4189 other->GetEffectDependency(), control);
4190 UpdateEffectDependency(effect);
4191
4192 // Introduce Phi nodes for values that have differing input at merge points,
4193 // potentially extending an existing Phi node if possible.
4194 for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4195 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4196 }
4197 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4198 contexts_[i] =
4199 builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4200 }
4201}
4202
4203
4204void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4205 bool is_osr) {
4206 int size = static_cast<int>(values()->size());
4207
4208 Node* control = builder_->NewLoop();
4209 if (assigned == nullptr) {
4210 // Assume that everything is updated in the loop.
4211 for (int i = 0; i < size; ++i) {
4212 values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4213 }
4214 } else {
4215 // Only build phis for those locals assigned in this loop.
4216 for (int i = 0; i < size; ++i) {
4217 if (i < assigned->length() && !assigned->Contains(i)) continue;
4218 Node* phi = builder_->NewPhi(1, values()->at(i), control);
4219 values()->at(i) = phi;
4220 }
4221 }
4222 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4223 UpdateEffectDependency(effect);
4224
4225 // Connect the loop to end via Terminate if it's not marked as unreachable.
4226 if (!IsMarkedAsUnreachable()) {
4227 // Connect the Loop node to end via a Terminate node.
4228 Node* terminate = builder_->graph()->NewNode(
4229 builder_->common()->Terminate(), effect, control);
4230 builder_->exit_controls_.push_back(terminate);
4231 }
4232
4233 if (builder_->info()->is_osr()) {
4234 // Introduce phis for all context values in the case of an OSR graph.
4235 for (size_t i = 0; i < contexts()->size(); ++i) {
4236 Node* context = contexts()->at(i);
4237 contexts()->at(i) = builder_->NewPhi(1, context, control);
4238 }
4239 }
4240
4241 if (is_osr) {
4242 // Merge OSR values as inputs to the phis of the loop.
4243 Graph* graph = builder_->graph();
4244 Node* osr_loop_entry = builder_->graph()->NewNode(
4245 builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4246
4247 builder_->MergeControl(control, osr_loop_entry);
4248 builder_->MergeEffect(effect, osr_loop_entry, control);
4249
4250 for (int i = 0; i < size; ++i) {
4251 Node* value = values()->at(i);
4252 Node* osr_value =
4253 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4254 values()->at(i) = builder_->MergeValue(value, osr_value, control);
4255 }
4256
4257 // Rename all the contexts in the environment.
4258 // The innermost context is the OSR value, and the outer contexts are
4259 // reconstructed by dynamically walking up the context chain.
4260 Node* osr_context = nullptr;
4261 const Operator* op =
4262 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4263 const Operator* op_inner =
4264 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4265 int last = static_cast<int>(contexts()->size() - 1);
4266 for (int i = last; i >= 0; i--) {
4267 Node* context = contexts()->at(i);
4268 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4269 : graph->NewNode(op, osr_context, osr_context,
4270 osr_loop_entry);
4271 contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4272 }
4273 }
4274}
4275
4276
4277Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4278 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4279 Node** buffer = EnsureInputBufferSize(count + 1);
4280 MemsetPointer(buffer, input, count);
4281 buffer[count] = control;
4282 return graph()->NewNode(phi_op, count + 1, buffer, true);
4283}
4284
4285
4286// TODO(mstarzinger): Revisit this once we have proper effect states.
4287Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4288 const Operator* phi_op = common()->EffectPhi(count);
4289 Node** buffer = EnsureInputBufferSize(count + 1);
4290 MemsetPointer(buffer, input, count);
4291 buffer[count] = control;
4292 return graph()->NewNode(phi_op, count + 1, buffer, true);
4293}
4294
4295
4296Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4297 int inputs = control->op()->ControlInputCount() + 1;
4298 if (control->opcode() == IrOpcode::kLoop) {
4299 // Control node for loop exists, add input.
4300 const Operator* op = common()->Loop(inputs);
4301 control->AppendInput(graph_zone(), other);
4302 NodeProperties::ChangeOp(control, op);
4303 } else if (control->opcode() == IrOpcode::kMerge) {
4304 // Control node for merge exists, add input.
4305 const Operator* op = common()->Merge(inputs);
4306 control->AppendInput(graph_zone(), other);
4307 NodeProperties::ChangeOp(control, op);
4308 } else {
4309 // Control node is a singleton, introduce a merge.
4310 const Operator* op = common()->Merge(inputs);
4311 Node* inputs[] = {control, other};
4312 control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4313 }
4314 return control;
4315}
4316
4317
4318Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4319 int inputs = control->op()->ControlInputCount();
4320 if (value->opcode() == IrOpcode::kEffectPhi &&
4321 NodeProperties::GetControlInput(value) == control) {
4322 // Phi already exists, add input.
4323 value->InsertInput(graph_zone(), inputs - 1, other);
4324 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4325 } else if (value != other) {
4326 // Phi does not exist yet, introduce one.
4327 value = NewEffectPhi(inputs, value, control);
4328 value->ReplaceInput(inputs - 1, other);
4329 }
4330 return value;
4331}
4332
4333
4334Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4335 int inputs = control->op()->ControlInputCount();
4336 if (value->opcode() == IrOpcode::kPhi &&
4337 NodeProperties::GetControlInput(value) == control) {
4338 // Phi already exists, add input.
4339 value->InsertInput(graph_zone(), inputs - 1, other);
4340 NodeProperties::ChangeOp(
4341 value, common()->Phi(MachineRepresentation::kTagged, inputs));
4342 } else if (value != other) {
4343 // Phi does not exist yet, introduce one.
4344 value = NewPhi(inputs, value, control);
4345 value->ReplaceInput(inputs - 1, other);
4346 }
4347 return value;
4348}
4349
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004350} // namespace compiler
4351} // namespace internal
4352} // namespace v8