blob: 89bb61949a0b04de404edd51bc3a38123304c0e2 [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 Murdochb8a8cc12014-11-26 15:28:44 +0000619 // Visit declarations within the function scope.
620 VisitDeclarations(scope->declarations());
621
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400622 // Build a stack-check before the body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 if (stack_check) {
624 Node* node = NewNode(javascript()->StackCheck());
625 PrepareFrameState(node, BailoutId::FunctionEntry());
626 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627
628 // Visit statements in the function body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 VisitStatements(info()->literal()->body());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 // Return 'undefined' in case we can fall off the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000632 BuildReturn(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633}
634
635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
637 if (!FLAG_analyze_environment_liveness ||
638 !info()->is_deoptimization_enabled()) {
639 return;
640 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 NonLiveFrameStateSlotReplacer replacer(
Ben Murdochda12d292016-06-02 14:46:10 +0100643 &state_values_cache_, jsgraph()->OptimizedOutConstant(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 liveness_analyzer()->local_count(), local_zone());
645 Variable* arguments = info()->scope()->arguments();
646 if (arguments != nullptr && arguments->IsStackAllocated()) {
647 replacer.MarkPermanentlyLive(arguments->index());
648 }
649 liveness_analyzer()->Run(&replacer);
650 if (FLAG_trace_environment_liveness) {
651 OFStream os(stdout);
652 liveness_analyzer()->Print(os);
653 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654}
655
656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657// Gets the bailout id just before reading a variable proxy, but only for
658// unallocated variables.
659static BailoutId BeforeId(VariableProxy* proxy) {
660 return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
661 : BailoutId::None();
662}
663
664
665static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
666#if DEBUG
667 const AstRawString* name = scope->parameter(index)->raw_name();
668 if (name && name->length() > 0) {
669 char* data = zone->NewArray<char>(name->length() + 1);
670 data[name->length()] = 0;
671 memcpy(data, name->raw_data(), name->length());
672 return data;
673 }
674#endif
675 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676}
677
678
679AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
680 Scope* scope,
681 Node* control_dependency)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 : builder_(builder),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 parameters_count_(scope->num_parameters() + 1),
684 locals_count_(scope->num_stack_slots()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685 liveness_block_(IsLivenessAnalysisEnabled()
686 ? builder_->liveness_analyzer()->NewBlock()
687 : nullptr),
688 values_(builder_->local_zone()),
689 contexts_(builder_->local_zone()),
690 control_dependency_(control_dependency),
691 effect_dependency_(control_dependency),
692 parameters_node_(nullptr),
693 locals_node_(nullptr),
694 stack_node_(nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
696
697 // Bind the receiver variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 int param_num = 0;
699 if (builder->info()->is_this_defined()) {
700 const Operator* op = common()->Parameter(param_num++, "%this");
701 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
702 values()->push_back(receiver);
703 } else {
704 values()->push_back(builder->jsgraph()->UndefinedConstant());
705 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706
707 // Bind all parameter variables. The parameter indices are shifted by 1
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 // (receiver is variable index -1 but {Parameter} node index 0 and located at
709 // index 0 in the environment).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710 for (int i = 0; i < scope->num_parameters(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
712 const Operator* op = common()->Parameter(param_num++, debug_name);
713 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 values()->push_back(parameter);
715 }
716
717 // Bind all local variables to undefined.
718 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
719 values()->insert(values()->end(), locals_count(), undefined_constant);
720}
721
722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
724 LivenessAnalyzerBlock* liveness_block)
725 : builder_(copy->builder_),
726 parameters_count_(copy->parameters_count_),
727 locals_count_(copy->locals_count_),
728 liveness_block_(liveness_block),
729 values_(copy->zone()),
730 contexts_(copy->zone()),
731 control_dependency_(copy->control_dependency_),
732 effect_dependency_(copy->effect_dependency_),
733 parameters_node_(copy->parameters_node_),
734 locals_node_(copy->locals_node_),
735 stack_node_(copy->stack_node_) {
736 const size_t kStackEstimate = 7; // optimum from experimentation!
737 values_.reserve(copy->values_.size() + kStackEstimate);
738 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
739 contexts_.reserve(copy->contexts_.size());
740 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
741 copy->contexts_.end());
742}
743
744
745void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
746 DCHECK(variable->IsStackAllocated());
747 if (variable->IsParameter()) {
748 // The parameter indices are shifted by 1 (receiver is variable
749 // index -1 but located at index 0 in the environment).
750 values()->at(variable->index() + 1) = node;
751 } else {
752 DCHECK(variable->IsStackLocal());
753 values()->at(variable->index() + parameters_count_) = node;
754 DCHECK(IsLivenessBlockConsistent());
755 if (liveness_block() != nullptr) {
756 liveness_block()->Bind(variable->index());
757 }
758 }
759}
760
761
762Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
763 DCHECK(variable->IsStackAllocated());
764 if (variable->IsParameter()) {
765 // The parameter indices are shifted by 1 (receiver is variable
766 // index -1 but located at index 0 in the environment).
767 return values()->at(variable->index() + 1);
768 } else {
769 DCHECK(variable->IsStackLocal());
770 DCHECK(IsLivenessBlockConsistent());
771 if (liveness_block() != nullptr) {
772 liveness_block()->Lookup(variable->index());
773 }
774 return values()->at(variable->index() + parameters_count_);
775 }
776}
777
778
779void AstGraphBuilder::Environment::MarkAllLocalsLive() {
780 DCHECK(IsLivenessBlockConsistent());
781 if (liveness_block() != nullptr) {
782 for (int i = 0; i < locals_count_; i++) {
783 liveness_block()->Lookup(i);
784 }
785 }
786}
787
788
789void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
790 DCHECK_LT(index, parameters_count());
791 values()->at(index) = node;
792}
793
794
795Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
796 DCHECK_LT(index, parameters_count());
797 return values()->at(index);
798}
799
800
801AstGraphBuilder::Environment*
802AstGraphBuilder::Environment::CopyForConditional() {
803 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
804 if (liveness_block() != nullptr) {
805 copy_liveness_block =
806 builder_->liveness_analyzer()->NewBlock(liveness_block());
807 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
808 }
809 return new (zone()) Environment(this, copy_liveness_block);
810}
811
812
813AstGraphBuilder::Environment*
814AstGraphBuilder::Environment::CopyAsUnreachable() {
815 Environment* env = new (zone()) Environment(this, nullptr);
816 env->MarkAsUnreachable();
817 return env;
818}
819
820
821AstGraphBuilder::Environment*
822AstGraphBuilder::Environment::CopyAndShareLiveness() {
823 if (liveness_block() != nullptr) {
824 // Finish the current liveness block before copying.
825 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
826 }
827 Environment* env = new (zone()) Environment(this, liveness_block());
828 return env;
829}
830
831
832AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
833 BitVector* assigned, bool is_osr) {
834 PrepareForLoop(assigned, is_osr);
835 return CopyAndShareLiveness();
836}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837
838
839void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
840 int offset, int count) {
841 bool should_update = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
843 if (*state_values == nullptr || (*state_values)->InputCount() != count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844 should_update = true;
845 } else {
846 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
847 for (int i = 0; i < count; i++) {
848 if ((*state_values)->InputAt(i) != env_values[i]) {
849 should_update = true;
850 break;
851 }
852 }
853 }
854 if (should_update) {
855 const Operator* op = common()->StateValues(count);
856 (*state_values) = graph()->NewNode(op, count, env_values);
857 }
858}
859
860
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
862 Node** state_values, int offset, int count) {
863 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
864 *state_values = builder_->state_values_cache_.GetNodeForValues(
865 env_values, static_cast<size_t>(count));
866}
867
Ben Murdoch097c5b22016-05-18 11:27:45 +0100868Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
869 OutputFrameStateCombine combine,
870 bool owner_has_exception) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871 if (!builder()->info()->is_deoptimization_enabled()) {
872 return builder()->jsgraph()->EmptyFrameState();
873 }
874
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 UpdateStateValues(&parameters_node_, 0, parameters_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
878 stack_height());
879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 const Operator* op = common()->FrameState(
881 ast_id, combine, builder()->frame_state_function_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000883 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
884 stack_node_, builder()->current_context(),
885 builder()->GetFunctionClosure(),
886 builder()->graph()->start());
887
888 DCHECK(IsLivenessBlockConsistent());
889 if (liveness_block() != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100890 // If the owning node has an exception, register the checkpoint to the
891 // predecessor so that the checkpoint is used for both the normal and the
892 // exceptional paths. Yes, this is a terrible hack and we might want
893 // to use an explicit frame state for the exceptional path.
894 if (owner_has_exception) {
895 liveness_block()->GetPredecessor()->Checkpoint(result);
896 } else {
897 liveness_block()->Checkpoint(result);
898 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 }
900 return result;
901}
902
903
904bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
905 return FLAG_analyze_environment_liveness &&
906 builder()->info()->is_deoptimization_enabled();
907}
908
909
910bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
911 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
912 (liveness_block() == nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913}
914
915
916AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
917 Expression::Context kind)
918 : kind_(kind), owner_(own), outer_(own->ast_context()) {
919 owner()->set_ast_context(this); // Push.
920#ifdef DEBUG
921 original_height_ = environment()->stack_height();
922#endif
923}
924
925
926AstGraphBuilder::AstContext::~AstContext() {
927 owner()->set_ast_context(outer_); // Pop.
928}
929
930
931AstGraphBuilder::AstEffectContext::~AstEffectContext() {
932 DCHECK(environment()->stack_height() == original_height_);
933}
934
935
936AstGraphBuilder::AstValueContext::~AstValueContext() {
937 DCHECK(environment()->stack_height() == original_height_ + 1);
938}
939
940
941AstGraphBuilder::AstTestContext::~AstTestContext() {
942 DCHECK(environment()->stack_height() == original_height_ + 1);
943}
944
945
946void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
947 // The value is ignored.
948}
949
950
951void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
952 environment()->Push(value);
953}
954
955
956void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957 environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958}
959
960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000961Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962
963
964Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
965 return environment()->Pop();
966}
967
968
969Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
970 return environment()->Pop();
971}
972
973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974Scope* AstGraphBuilder::current_scope() const {
975 return execution_context_->scope();
976}
977
978
979Node* AstGraphBuilder::current_context() const {
980 return environment()->Context();
981}
982
983
984void AstGraphBuilder::ControlScope::PerformCommand(Command command,
985 Statement* target,
986 Node* value) {
987 Environment* env = environment()->CopyAsUnreachable();
988 ControlScope* current = this;
989 while (current != nullptr) {
990 environment()->TrimStack(current->stack_height());
991 environment()->TrimContextChain(current->context_length());
992 if (current->Execute(command, target, value)) break;
993 current = current->outer_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000994 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 builder()->set_environment(env);
996 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997}
998
999
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
1001 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002}
1003
1004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
1006 PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
1007}
1008
1009
1010void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
1011 PerformCommand(CMD_RETURN, nullptr, return_value);
1012}
1013
1014
1015void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
1016 PerformCommand(CMD_THROW, nullptr, exception_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017}
1018
1019
1020void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 if (expr == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 return environment()->Push(jsgraph()->NullConstant());
1023 }
1024 VisitForValue(expr);
1025}
1026
1027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1029 if (expr == nullptr) {
1030 return environment()->Push(jsgraph()->TheHoleConstant());
1031 }
1032 VisitForValue(expr);
1033}
1034
1035
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1037 for (int i = 0; i < exprs->length(); ++i) {
1038 VisitForValue(exprs->at(i));
1039 }
1040}
1041
1042
1043void AstGraphBuilder::VisitForValue(Expression* expr) {
1044 AstValueContext for_value(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001045 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001047 } else {
1048 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 }
1050}
1051
1052
1053void AstGraphBuilder::VisitForEffect(Expression* expr) {
1054 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001055 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057 } else {
1058 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059 }
1060}
1061
1062
1063void AstGraphBuilder::VisitForTest(Expression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 AstTestContext for_condition(this, expr->test_id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001066 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001067 } else {
1068 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1069 }
1070}
1071
1072
1073void AstGraphBuilder::Visit(Expression* expr) {
1074 // Reuses enclosing AstContext.
1075 if (!CheckStackOverflow()) {
1076 expr->Accept(this);
1077 } else {
1078 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079 }
1080}
1081
1082
1083void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1084 Variable* variable = decl->proxy()->var();
1085 VariableMode mode = decl->mode();
1086 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
1087 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 case VariableLocation::GLOBAL:
1089 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001090 Handle<Oddball> value = variable->binding_needs_init()
1091 ? isolate()->factory()->the_hole_value()
1092 : isolate()->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001093 globals()->push_back(variable->name());
1094 globals()->push_back(value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095 break;
1096 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 case VariableLocation::PARAMETER:
1098 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099 if (hole_init) {
1100 Node* value = jsgraph()->TheHoleConstant();
1101 environment()->Bind(variable, value);
1102 }
1103 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 case VariableLocation::CONTEXT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 if (hole_init) {
1106 Node* value = jsgraph()->TheHoleConstant();
1107 const Operator* op = javascript()->StoreContext(0, variable->index());
1108 NewNode(op, current_context(), value);
1109 }
1110 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 UNIMPLEMENTED();
1113 }
1114}
1115
1116
1117void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1118 Variable* variable = decl->proxy()->var();
1119 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 case VariableLocation::GLOBAL:
1121 case VariableLocation::UNALLOCATED: {
1122 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1123 decl->fun(), info()->script(), info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124 // Check for stack-overflow exception.
1125 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001126 globals()->push_back(variable->name());
1127 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 break;
1129 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 case VariableLocation::PARAMETER:
1131 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132 VisitForValue(decl->fun());
1133 Node* value = environment()->Pop();
1134 environment()->Bind(variable, value);
1135 break;
1136 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001138 VisitForValue(decl->fun());
1139 Node* value = environment()->Pop();
1140 const Operator* op = javascript()->StoreContext(0, variable->index());
1141 NewNode(op, current_context(), value);
1142 break;
1143 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 case VariableLocation::LOOKUP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 UNIMPLEMENTED();
1146 }
1147}
1148
1149
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1151 UNREACHABLE();
1152}
1153
1154
1155void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1156 UNREACHABLE();
1157}
1158
1159
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160void AstGraphBuilder::VisitBlock(Block* stmt) {
1161 BlockBuilder block(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 ControlScopeForBreakable scope(this, stmt, &block);
1163 if (stmt->labels() != nullptr) block.BeginBlock();
1164 if (stmt->scope() == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 // Visit statements in the same scope, no declarations.
1166 VisitStatements(stmt->statements());
1167 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 // Visit declarations and statements in a block scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 if (stmt->scope()->NeedsContext()) {
1170 Node* context = BuildLocalBlockContext(stmt->scope());
1171 ContextScope scope(this, stmt->scope(), context);
1172 VisitDeclarations(stmt->scope()->declarations());
1173 VisitStatements(stmt->statements());
1174 } else {
1175 VisitDeclarations(stmt->scope()->declarations());
1176 VisitStatements(stmt->statements());
1177 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001178 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 if (stmt->labels() != nullptr) block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180}
1181
1182
1183void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1184 VisitForEffect(stmt->expression());
1185}
1186
1187
1188void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1189 // Do nothing.
1190}
1191
1192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001193void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1194 SloppyBlockFunctionStatement* stmt) {
1195 Visit(stmt->statement());
1196}
1197
1198
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1200 IfBuilder compare_if(this);
1201 VisitForTest(stmt->condition());
1202 Node* condition = environment()->Pop();
1203 compare_if.If(condition);
1204 compare_if.Then();
1205 Visit(stmt->then_statement());
1206 compare_if.Else();
1207 Visit(stmt->else_statement());
1208 compare_if.End();
1209}
1210
1211
1212void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 execution_control()->ContinueTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214}
1215
1216
1217void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218 execution_control()->BreakTo(stmt->target());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001219}
1220
1221
1222void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1223 VisitForValue(stmt->expression());
1224 Node* result = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001225 execution_control()->ReturnValue(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226}
1227
1228
1229void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1230 VisitForValue(stmt->expression());
1231 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 Node* object = BuildToObject(value, stmt->ToObjectId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 const Operator* op = javascript()->CreateWithContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 Node* context = NewNode(op, object, GetFunctionClosureForContext());
1235 PrepareFrameState(context, stmt->EntryId());
1236 VisitInScope(stmt->statement(), stmt->scope(), context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237}
1238
1239
1240void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1241 ZoneList<CaseClause*>* clauses = stmt->cases();
1242 SwitchBuilder compare_switch(this, clauses->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001243 ControlScopeForBreakable scope(this, stmt, &compare_switch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 compare_switch.BeginSwitch();
1245 int default_index = -1;
1246
1247 // Keep the switch value on the stack until a case matches.
1248 VisitForValue(stmt->tag());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249
1250 // Iterate over all cases and create nodes for label comparison.
1251 for (int i = 0; i < clauses->length(); i++) {
1252 CaseClause* clause = clauses->at(i);
1253
1254 // The default is not a test, remember index.
1255 if (clause->is_default()) {
1256 default_index = i;
1257 continue;
1258 }
1259
1260 // Create nodes to perform label comparison as if via '==='. The switch
1261 // value is still on the operand stack while the label is evaluated.
1262 VisitForValue(clause->label());
1263 Node* label = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264 Node* tag = environment()->Top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265 const Operator* op = javascript()->StrictEqual();
1266 Node* condition = NewNode(op, tag, label);
1267 compare_switch.BeginLabel(i, condition);
1268
1269 // Discard the switch value at label match.
1270 environment()->Pop();
1271 compare_switch.EndLabel();
1272 }
1273
1274 // Discard the switch value and mark the default case.
1275 environment()->Pop();
1276 if (default_index >= 0) {
1277 compare_switch.DefaultAt(default_index);
1278 }
1279
1280 // Iterate over all cases and create nodes for case bodies.
1281 for (int i = 0; i < clauses->length(); i++) {
1282 CaseClause* clause = clauses->at(i);
1283 compare_switch.BeginCase(i);
1284 VisitStatements(clause->statements());
1285 compare_switch.EndCase();
1286 }
1287
1288 compare_switch.EndSwitch();
1289}
1290
1291
1292void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1293 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1295 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 while_loop.EndBody();
1297 VisitForTest(stmt->cond());
1298 Node* condition = environment()->Pop();
1299 while_loop.BreakUnless(condition);
1300 while_loop.EndLoop();
1301}
1302
1303
1304void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1305 LoopBuilder while_loop(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 VisitForTest(stmt->cond());
1308 Node* condition = environment()->Pop();
1309 while_loop.BreakUnless(condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 VisitIterationBody(stmt, &while_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 while_loop.EndBody();
1312 while_loop.EndLoop();
1313}
1314
1315
1316void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1317 LoopBuilder for_loop(this);
1318 VisitIfNotNull(stmt->init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1320 if (stmt->cond() != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321 VisitForTest(stmt->cond());
1322 Node* condition = environment()->Pop();
1323 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001324 } else {
1325 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 for_loop.EndBody();
1329 VisitIfNotNull(stmt->next());
1330 for_loop.EndLoop();
1331}
1332
1333
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1335 VisitForValue(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 Node* object = environment()->Pop();
1337 BlockBuilder for_block(this);
1338 for_block.BeginBlock();
1339 // Check for null or undefined before entering loop.
1340 Node* is_null_cond =
1341 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1342 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1343 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1344 jsgraph()->UndefinedConstant());
1345 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 // Convert object to jsobject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001348 object = BuildToObject(object, stmt->ToObjectId());
1349 environment()->Push(object);
1350
1351 // Prepare for-in cache.
1352 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001353 PrepareFrameState(prepare, stmt->PrepareId(),
1354 OutputFrameStateCombine::Push(3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 Node* cache_type = NewNode(common()->Projection(0), prepare);
1356 Node* cache_array = NewNode(common()->Projection(1), prepare);
1357 Node* cache_length = NewNode(common()->Projection(2), prepare);
1358
1359 // Construct the rest of the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 environment()->Push(cache_type);
1361 environment()->Push(cache_array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001362 environment()->Push(cache_length);
1363 environment()->Push(jsgraph()->ZeroConstant());
1364
1365 // Build the actual loop body.
1366 LoopBuilder for_loop(this);
1367 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 // These stack values are renamed in the case of OSR, so reload them
1370 // from the environment.
1371 Node* index = environment()->Peek(0);
1372 Node* cache_length = environment()->Peek(1);
1373 Node* cache_array = environment()->Peek(2);
1374 Node* cache_type = environment()->Peek(3);
1375 Node* object = environment()->Peek(4);
1376
1377 // Check loop termination condition.
1378 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1379 for_loop.BreakWhen(exit_cond);
1380
1381 // Compute the next enumerated value.
1382 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1383 cache_type, index);
1384 PrepareFrameState(value, stmt->FilterId(),
1385 OutputFrameStateCombine::Push());
1386 IfBuilder test_value(this);
1387 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1388 jsgraph()->UndefinedConstant());
1389 test_value.If(test_value_cond, BranchHint::kFalse);
1390 test_value.Then();
1391 test_value.Else();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001393 // Bind value and do loop body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 VectorSlotPair feedback =
1395 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1396 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1397 stmt->AssignmentId());
1398 VisitIterationBody(stmt, &for_loop);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001400 test_value.End();
1401 index = environment()->Peek(0);
1402 for_loop.EndBody();
1403
1404 // Increment counter and continue.
1405 index = NewNode(javascript()->ForInStep(), index);
1406 environment()->Poke(0, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 for_loop.EndLoop();
1409 environment()->Drop(5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001410 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 for_block.EndBlock();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412}
1413
1414
1415void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 LoopBuilder for_loop(this);
1417 VisitForEffect(stmt->assign_iterator());
1418 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1419 VisitForEffect(stmt->next_result());
1420 VisitForTest(stmt->result_done());
1421 Node* condition = environment()->Pop();
1422 for_loop.BreakWhen(condition);
1423 VisitForEffect(stmt->assign_each());
1424 VisitIterationBody(stmt, &for_loop);
1425 for_loop.EndBody();
1426 for_loop.EndLoop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427}
1428
1429
1430void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431 TryCatchBuilder try_control(this);
1432
1433 // Evaluate the try-block inside a control scope. This simulates a handler
1434 // that is intercepting 'throw' control commands.
1435 try_control.BeginTry();
1436 {
1437 ControlScopeForCatch scope(this, &try_control);
1438 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1439 environment()->Push(current_context());
1440 Visit(stmt->try_block());
1441 environment()->Pop();
1442 }
1443 try_control.EndTry();
1444
Ben Murdochda12d292016-06-02 14:46:10 +01001445 // If requested, clear message object as we enter the catch block.
1446 if (stmt->clear_pending_message()) {
1447 Node* the_hole = jsgraph()->TheHoleConstant();
1448 NewNode(javascript()->StoreMessage(), the_hole);
1449 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450
1451 // Create a catch scope that binds the exception.
1452 Node* exception = try_control.GetExceptionNode();
1453 Handle<String> name = stmt->variable()->name();
1454 const Operator* op = javascript()->CreateCatchContext(name);
1455 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1456
1457 // Evaluate the catch-block.
1458 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1459 try_control.EndCatch();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460}
1461
1462
1463void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001464 TryFinallyBuilder try_control(this);
1465
1466 // We keep a record of all paths that enter the finally-block to be able to
1467 // dispatch to the correct continuation point after the statements in the
1468 // finally-block have been evaluated.
1469 //
1470 // The try-finally construct can enter the finally-block in three ways:
1471 // 1. By exiting the try-block normally, falling through at the end.
1472 // 2. By exiting the try-block with a function-local control flow transfer
1473 // (i.e. through break/continue/return statements).
1474 // 3. By exiting the try-block with a thrown exception.
1475 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1476 ControlScope::DeferredCommands* commands =
1477 new (local_zone()) ControlScope::DeferredCommands(this);
1478
1479 // Evaluate the try-block inside a control scope. This simulates a handler
1480 // that is intercepting all control commands.
1481 try_control.BeginTry();
1482 {
1483 ControlScopeForFinally scope(this, commands, &try_control);
1484 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1485 environment()->Push(current_context());
1486 Visit(stmt->try_block());
1487 environment()->Pop();
1488 }
1489 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001491 // The result value semantics depend on how the block was entered:
1492 // - ReturnStatement: It represents the return value being returned.
1493 // - ThrowStatement: It represents the exception being thrown.
1494 // - BreakStatement/ContinueStatement: Filled with the hole.
1495 // - Falling through into finally-block: Filled with the hole.
1496 Node* result = try_control.GetResultValueNode();
1497 Node* token = try_control.GetDispatchTokenNode();
1498
1499 // The result value, dispatch token and message is expected on the operand
1500 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1501 Node* message = NewNode(javascript()->LoadMessage());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001502 environment()->Push(token);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001503 environment()->Push(result);
1504 environment()->Push(message);
1505
1506 // Clear message object as we enter the finally block.
1507 Node* the_hole = jsgraph()->TheHoleConstant();
1508 NewNode(javascript()->StoreMessage(), the_hole);
1509
1510 // Evaluate the finally-block.
1511 Visit(stmt->finally_block());
1512 try_control.EndFinally();
1513
1514 // The result value, dispatch token and message is restored from the operand
1515 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1516 message = environment()->Pop();
1517 result = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001518 token = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 NewNode(javascript()->StoreMessage(), message);
1520
1521 // Dynamic dispatch after the finally-block.
1522 commands->ApplyDeferredCommands(token, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523}
1524
1525
1526void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527 Node* node =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001528 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 PrepareFrameState(node, stmt->DebugBreakId());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 environment()->MarkAllLocalsLive();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531}
1532
1533
1534void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535 // Find or build a shared function info.
1536 Handle<SharedFunctionInfo> shared_info =
1537 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1538 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539
1540 // Create node to instantiate a new closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541 PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1542 const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1543 Node* value = NewNode(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 ast_context()->ProduceValue(value);
1545}
1546
1547
1548void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 // Visit declarations and class literal in a block scope.
1550 if (expr->scope()->ContextLocalCount() > 0) {
1551 Node* context = BuildLocalBlockContext(expr->scope());
1552 ContextScope scope(this, expr->scope(), context);
1553 VisitDeclarations(expr->scope()->declarations());
1554 VisitClassLiteralContents(expr);
1555 } else {
1556 VisitDeclarations(expr->scope()->declarations());
1557 VisitClassLiteralContents(expr);
1558 }
1559}
1560
1561
1562void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001563 VisitForValueOrTheHole(expr->extends());
1564 VisitForValue(expr->constructor());
1565
1566 // Create node to instantiate a new class.
1567 Node* constructor = environment()->Pop();
1568 Node* extends = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 Node* start = jsgraph()->Constant(expr->start_position());
1570 Node* end = jsgraph()->Constant(expr->end_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001571 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
1572 Node* literal = NewNode(opc, extends, constructor, start, end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 PrepareFrameState(literal, expr->CreateLiteralId(),
1574 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 environment()->Push(literal);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001576
1577 // Load the "prototype" from the constructor.
1578 FrameStateBeforeAndAfter states(this, expr->CreateLiteralId());
1579 Handle<Name> name = isolate()->factory()->prototype_string();
1580 VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
1581 Node* prototype = BuildNamedLoad(literal, name, pair);
1582 states.AddToNode(prototype, expr->PrototypeId(),
1583 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 environment()->Push(prototype);
1585
1586 // Create nodes to store method values into the literal.
1587 for (int i = 0; i < expr->properties()->length(); i++) {
1588 ObjectLiteral::Property* property = expr->properties()->at(i);
1589 environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1590
1591 VisitForValue(property->key());
1592 Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1593 environment()->Push(name);
1594
1595 // The static prototype property is read only. We handle the non computed
1596 // property name case in the parser. Since this is the only case where we
1597 // need to check for an own read only property we special case this so we do
1598 // not need to do this for every property.
1599 if (property->is_static() && property->is_computed_name()) {
1600 Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1601 expr->GetIdForProperty(i));
1602 environment()->Push(check);
1603 }
1604
1605 VisitForValue(property->value());
1606 Node* value = environment()->Pop();
1607 Node* key = environment()->Pop();
1608 Node* receiver = environment()->Pop();
1609
1610 BuildSetHomeObject(value, receiver, property);
1611
1612 switch (property->kind()) {
1613 case ObjectLiteral::Property::CONSTANT:
1614 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1615 case ObjectLiteral::Property::PROTOTYPE:
1616 UNREACHABLE();
1617 case ObjectLiteral::Property::COMPUTED: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001618 Node* attr = jsgraph()->Constant(DONT_ENUM);
1619 Node* set_function_name =
1620 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001622 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1623 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 break;
1625 }
1626 case ObjectLiteral::Property::GETTER: {
1627 Node* attr = jsgraph()->Constant(DONT_ENUM);
1628 const Operator* op = javascript()->CallRuntime(
1629 Runtime::kDefineGetterPropertyUnchecked, 4);
1630 NewNode(op, receiver, key, value, attr);
1631 break;
1632 }
1633 case ObjectLiteral::Property::SETTER: {
1634 Node* attr = jsgraph()->Constant(DONT_ENUM);
1635 const Operator* op = javascript()->CallRuntime(
1636 Runtime::kDefineSetterPropertyUnchecked, 4);
1637 NewNode(op, receiver, key, value, attr);
1638 break;
1639 }
1640 }
1641 }
1642
Ben Murdochda12d292016-06-02 14:46:10 +01001643 // Set both the prototype and constructor to have fast properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001644 prototype = environment()->Pop();
1645 literal = environment()->Pop();
1646 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001647 javascript()->CallRuntime(Runtime::kFinalizeClassDefinition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 literal = NewNode(op, literal, prototype);
1649
1650 // Assign to class variable.
1651 if (expr->class_variable_proxy() != nullptr) {
1652 Variable* var = expr->class_variable_proxy()->var();
1653 FrameStateBeforeAndAfter states(this, BailoutId::None());
1654 VectorSlotPair feedback = CreateVectorSlotPair(
1655 expr->NeedsProxySlot() ? expr->ProxySlot()
1656 : FeedbackVectorSlot::Invalid());
1657 BuildVariableAssignment(var, literal, Token::INIT, feedback,
1658 BailoutId::None(), states);
1659 }
1660 ast_context()->ProduceValue(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661}
1662
1663
1664void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1665 UNREACHABLE();
1666}
1667
1668
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1670 VisitBlock(expr->block());
1671 VisitVariableProxy(expr->result());
1672 ast_context()->ReplaceValue();
1673}
1674
1675
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676void AstGraphBuilder::VisitConditional(Conditional* expr) {
1677 IfBuilder compare_if(this);
1678 VisitForTest(expr->condition());
1679 Node* condition = environment()->Pop();
1680 compare_if.If(condition);
1681 compare_if.Then();
1682 Visit(expr->then_expression());
1683 compare_if.Else();
1684 Visit(expr->else_expression());
1685 compare_if.End();
1686 ast_context()->ReplaceValue();
1687}
1688
1689
1690void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001691 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001692 FrameStateBeforeAndAfter states(this, BeforeId(expr));
1693 Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
1694 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 ast_context()->ProduceValue(value);
1696}
1697
1698
1699void AstGraphBuilder::VisitLiteral(Literal* expr) {
1700 Node* value = jsgraph()->Constant(expr->value());
1701 ast_context()->ProduceValue(value);
1702}
1703
1704
1705void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1706 Node* closure = GetFunctionClosure();
1707
1708 // Create node to materialize a regular expression literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001709 const Operator* op = javascript()->CreateLiteralRegExp(
1710 expr->pattern(), expr->flags(), expr->literal_index());
1711 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001712 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 ast_context()->ProduceValue(literal);
1714}
1715
1716
1717void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1718 Node* closure = GetFunctionClosure();
1719
1720 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001721 const Operator* op = javascript()->CreateLiteralObject(
1722 expr->constant_properties(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001723 expr->literal_index(), expr->properties_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724 Node* literal = NewNode(op, closure);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001725 PrepareFrameState(literal, expr->CreateLiteralId(),
1726 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727
1728 // The object is expected on the operand stack during computation of the
1729 // property values and is the value of the entire expression.
1730 environment()->Push(literal);
1731
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001732 // Create nodes to store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001733 int property_index = 0;
1734 AccessorTable accessor_table(local_zone());
1735 for (; property_index < expr->properties()->length(); property_index++) {
1736 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1737 if (property->is_computed_name()) break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001738 if (property->IsCompileTimeValue()) continue;
1739
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001740 Literal* key = property->key()->AsLiteral();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741 switch (property->kind()) {
1742 case ObjectLiteral::Property::CONSTANT:
1743 UNREACHABLE();
1744 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1745 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1746 // Fall through.
1747 case ObjectLiteral::Property::COMPUTED: {
1748 // It is safe to use [[Put]] here because the boilerplate already
1749 // contains computed properties with an uninitialized value.
1750 if (key->value()->IsInternalizedString()) {
1751 if (property->emit_store()) {
1752 VisitForValue(property->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001753 FrameStateBeforeAndAfter states(this, property->value()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001754 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 Node* literal = environment()->Top();
1756 Handle<Name> name = key->AsPropertyName();
1757 VectorSlotPair feedback =
1758 CreateVectorSlotPair(property->GetSlot(0));
1759 Node* store = BuildNamedStore(literal, name, value, feedback);
1760 states.AddToNode(store, key->id(),
1761 OutputFrameStateCombine::Ignore());
1762 BuildSetHomeObject(value, literal, property, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 } else {
1764 VisitForEffect(property->value());
1765 }
1766 break;
1767 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 VisitForValue(property->key());
1770 VisitForValue(property->value());
1771 Node* value = environment()->Pop();
1772 Node* key = environment()->Pop();
1773 Node* receiver = environment()->Pop();
1774 if (property->emit_store()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001775 Node* language = jsgraph()->Constant(SLOPPY);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001776 const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 Node* set_property = NewNode(op, receiver, key, value, language);
1778 // SetProperty should not lazy deopt on an object literal.
1779 PrepareFrameState(set_property, BailoutId::None());
1780 BuildSetHomeObject(value, receiver, property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001781 }
1782 break;
1783 }
1784 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 environment()->Push(environment()->Top()); // Duplicate receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 VisitForValue(property->value());
1787 Node* value = environment()->Pop();
1788 Node* receiver = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001789 DCHECK(property->emit_store());
1790 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001791 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001792 Node* set_prototype = NewNode(op, receiver, value);
1793 // SetPrototype should not lazy deopt on an object literal.
1794 PrepareFrameState(set_prototype,
1795 expr->GetIdForPropertySet(property_index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001796 break;
1797 }
1798 case ObjectLiteral::Property::GETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 if (property->emit_store()) {
1800 accessor_table.lookup(key)->second->getter = property;
1801 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 break;
1803 case ObjectLiteral::Property::SETTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 if (property->emit_store()) {
1805 accessor_table.lookup(key)->second->setter = property;
1806 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807 break;
1808 }
1809 }
1810
1811 // Create nodes to define accessors, using only a single call to the runtime
1812 // for each pair of corresponding getters and setters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001813 literal = environment()->Top(); // Reload from operand stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001814 for (AccessorTable::Iterator it = accessor_table.begin();
1815 it != accessor_table.end(); ++it) {
1816 VisitForValue(it->first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 VisitObjectLiteralAccessor(literal, it->second->getter);
1818 VisitObjectLiteralAccessor(literal, it->second->setter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 Node* setter = environment()->Pop();
1820 Node* getter = environment()->Pop();
1821 Node* name = environment()->Pop();
1822 Node* attr = jsgraph()->Constant(NONE);
1823 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001824 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001825 Node* call = NewNode(op, literal, name, getter, setter, attr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001826 // This should not lazy deopt on a new literal.
1827 PrepareFrameState(call, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 }
1829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 // Object literals have two parts. The "static" part on the left contains no
1831 // computed property names, and so we can compute its map ahead of time; see
1832 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1833 // with the first computed property name and continues with all properties to
1834 // its right. All the code from above initializes the static component of the
1835 // object literal, and arranges for the map of the result to reflect the
1836 // static order in which the keys appear. For the dynamic properties, we
1837 // compile them into a series of "SetOwnProperty" runtime calls. This will
1838 // preserve insertion order.
1839 for (; property_index < expr->properties()->length(); property_index++) {
1840 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1841
1842 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1843 environment()->Push(environment()->Top()); // Duplicate receiver.
1844 VisitForValue(property->value());
1845 Node* value = environment()->Pop();
1846 Node* receiver = environment()->Pop();
1847 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001848 javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001849 Node* call = NewNode(op, receiver, value);
1850 PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1851 continue;
1852 }
1853
1854 environment()->Push(environment()->Top()); // Duplicate receiver.
1855 VisitForValue(property->key());
1856 Node* name = BuildToName(environment()->Pop(),
1857 expr->GetIdForPropertyName(property_index));
1858 environment()->Push(name);
1859 VisitForValue(property->value());
1860 Node* value = environment()->Pop();
1861 Node* key = environment()->Pop();
1862 Node* receiver = environment()->Pop();
1863 BuildSetHomeObject(value, receiver, property);
1864 switch (property->kind()) {
1865 case ObjectLiteral::Property::CONSTANT:
1866 case ObjectLiteral::Property::COMPUTED:
1867 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1868 Node* attr = jsgraph()->Constant(NONE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001869 Node* set_function_name =
1870 jsgraph()->Constant(property->NeedsSetFunctionName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001871 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001872 javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1873 NewNode(op, receiver, key, value, attr, set_function_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001874 break;
1875 }
1876 case ObjectLiteral::Property::PROTOTYPE:
1877 UNREACHABLE(); // Handled specially above.
1878 break;
1879 case ObjectLiteral::Property::GETTER: {
1880 Node* attr = jsgraph()->Constant(NONE);
1881 const Operator* op = javascript()->CallRuntime(
1882 Runtime::kDefineGetterPropertyUnchecked, 4);
1883 Node* call = NewNode(op, receiver, key, value, attr);
1884 PrepareFrameState(call, BailoutId::None());
1885 break;
1886 }
1887 case ObjectLiteral::Property::SETTER: {
1888 Node* attr = jsgraph()->Constant(NONE);
1889 const Operator* op = javascript()->CallRuntime(
1890 Runtime::kDefineSetterPropertyUnchecked, 4);
1891 Node* call = NewNode(op, receiver, key, value, attr);
1892 PrepareFrameState(call, BailoutId::None());
1893 break;
1894 }
1895 }
1896 }
1897
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001898 ast_context()->ProduceValue(environment()->Pop());
1899}
1900
1901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001902void AstGraphBuilder::VisitObjectLiteralAccessor(
1903 Node* home_object, ObjectLiteralProperty* property) {
1904 if (property == nullptr) {
1905 VisitForValueOrNull(nullptr);
1906 } else {
1907 VisitForValue(property->value());
1908 BuildSetHomeObject(environment()->Top(), home_object, property);
1909 }
1910}
1911
1912
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001913void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1914 Node* closure = GetFunctionClosure();
1915
1916 // Create node to deep-copy the literal boilerplate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001917 const Operator* op = javascript()->CreateLiteralArray(
1918 expr->constant_elements(), expr->ComputeFlags(true),
Ben Murdochda12d292016-06-02 14:46:10 +01001919 expr->literal_index(), expr->values()->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001920 Node* literal = NewNode(op, closure);
1921 PrepareFrameState(literal, expr->CreateLiteralId(),
1922 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 // The array is expected on the operand stack during computation of the
1925 // element values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001926 environment()->Push(literal);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001927
1928 // Create nodes to evaluate all the non-constant subexpressions and to store
1929 // them into the newly cloned array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001930 int array_index = 0;
1931 for (; array_index < expr->values()->length(); array_index++) {
1932 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001933 DCHECK(!subexpr->IsSpread());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001934 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1935
1936 VisitForValue(subexpr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001937 {
1938 FrameStateBeforeAndAfter states(this, subexpr->id());
1939 VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1940 Node* value = environment()->Pop();
1941 Node* index = jsgraph()->Constant(array_index);
1942 Node* literal = environment()->Top();
1943 Node* store = BuildKeyedStore(literal, index, value, pair);
1944 states.AddToNode(store, expr->GetIdForElement(array_index),
1945 OutputFrameStateCombine::Ignore());
1946 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001947 }
1948
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001949 // In case the array literal contains spread expressions it has two parts. The
1950 // first part is the "static" array which has a literal index is handled
1951 // above. The second part is the part after the first spread expression
1952 // (inclusive) and these elements gets appended to the array. Note that the
1953 // number elements an iterable produces is unknown ahead of time.
1954 for (; array_index < expr->values()->length(); array_index++) {
1955 Expression* subexpr = expr->values()->at(array_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001956 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001957
Ben Murdoch097c5b22016-05-18 11:27:45 +01001958 VisitForValue(subexpr);
1959 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001960 Node* value = environment()->Pop();
1961 Node* array = environment()->Pop();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001962 const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
1963 Node* result = NewNode(op, array, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001964 PrepareFrameState(result, expr->GetIdForElement(array_index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001965 environment()->Push(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001966 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001967 }
1968
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001969 ast_context()->ProduceValue(environment()->Pop());
1970}
1971
1972
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001973void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
1974 const VectorSlotPair& feedback,
1975 BailoutId bailout_id_before,
1976 BailoutId bailout_id_after) {
1977 DCHECK(expr->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001978
1979 // Left-hand side can only be a property, a global or a variable slot.
1980 Property* property = expr->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001981 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001982
1983 // Evaluate LHS expression and store the value.
1984 switch (assign_type) {
1985 case VARIABLE: {
1986 Variable* var = expr->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001987 environment()->Push(value);
1988 FrameStateBeforeAndAfter states(this, bailout_id_before);
1989 value = environment()->Pop();
1990 BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
1991 bailout_id_after, states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001992 break;
1993 }
1994 case NAMED_PROPERTY: {
1995 environment()->Push(value);
1996 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001997 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001998 Node* object = environment()->Pop();
1999 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002000 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2001 Node* store = BuildNamedStore(object, name, value, feedback);
2002 states.AddToNode(store, bailout_id_after,
2003 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004 break;
2005 }
2006 case KEYED_PROPERTY: {
2007 environment()->Push(value);
2008 VisitForValue(property->obj());
2009 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002010 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002011 Node* key = environment()->Pop();
2012 Node* object = environment()->Pop();
2013 value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002014 Node* store = BuildKeyedStore(object, key, value, feedback);
2015 states.AddToNode(store, bailout_id_after,
2016 OutputFrameStateCombine::Ignore());
2017 break;
2018 }
2019 case NAMED_SUPER_PROPERTY: {
2020 environment()->Push(value);
2021 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2022 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2023 FrameStateBeforeAndAfter states(this, property->obj()->id());
2024 Node* home_object = environment()->Pop();
2025 Node* receiver = environment()->Pop();
2026 value = environment()->Pop();
2027 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2028 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2029 states.AddToNode(store, bailout_id_after,
2030 OutputFrameStateCombine::Ignore());
2031 break;
2032 }
2033 case KEYED_SUPER_PROPERTY: {
2034 environment()->Push(value);
2035 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2036 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2037 VisitForValue(property->key());
2038 FrameStateBeforeAndAfter states(this, property->key()->id());
2039 Node* key = environment()->Pop();
2040 Node* home_object = environment()->Pop();
2041 Node* receiver = environment()->Pop();
2042 value = environment()->Pop();
2043 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2044 states.AddToNode(store, bailout_id_after,
2045 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002046 break;
2047 }
2048 }
2049}
2050
2051
2052void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002053 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002054
2055 // Left-hand side can only be a property, a global or a variable slot.
2056 Property* property = expr->target()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002057 LhsKind assign_type = Property::GetAssignType(property);
2058 bool needs_frame_state_before = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002059
2060 // Evaluate LHS expression.
2061 switch (assign_type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002062 case VARIABLE: {
2063 Variable* variable = expr->target()->AsVariableProxy()->var();
2064 if (variable->location() == VariableLocation::PARAMETER ||
2065 variable->location() == VariableLocation::LOCAL ||
2066 variable->location() == VariableLocation::CONTEXT) {
2067 needs_frame_state_before = false;
2068 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002069 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002070 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 case NAMED_PROPERTY:
2072 VisitForValue(property->obj());
2073 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002074 case KEYED_PROPERTY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002075 VisitForValue(property->obj());
2076 VisitForValue(property->key());
2077 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002078 case NAMED_SUPER_PROPERTY:
2079 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2080 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2081 break;
2082 case KEYED_SUPER_PROPERTY:
2083 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2084 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2085 VisitForValue(property->key());
2086 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087 }
2088
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002089 BailoutId before_store_id = BailoutId::None();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090 // Evaluate the value and potentially handle compound assignments by loading
2091 // the left-hand side value and performing a binary operation.
2092 if (expr->is_compound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002093 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002094 switch (assign_type) {
2095 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002096 VariableProxy* proxy = expr->target()->AsVariableProxy();
2097 VectorSlotPair pair =
2098 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002099 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2100 old_value =
2101 BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
2102 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103 break;
2104 }
2105 case NAMED_PROPERTY: {
2106 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002107 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002108 VectorSlotPair pair =
2109 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002110 FrameStateBeforeAndAfter states(this, property->obj()->id());
2111 old_value = BuildNamedLoad(object, name, pair);
2112 states.AddToNode(old_value, property->LoadId(),
2113 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002114 break;
2115 }
2116 case KEYED_PROPERTY: {
2117 Node* key = environment()->Top();
2118 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002119 VectorSlotPair pair =
2120 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002121 FrameStateBeforeAndAfter states(this, property->key()->id());
2122 old_value = BuildKeyedLoad(object, key, pair);
2123 states.AddToNode(old_value, property->LoadId(),
2124 OutputFrameStateCombine::Push());
2125 break;
2126 }
2127 case NAMED_SUPER_PROPERTY: {
2128 Node* home_object = environment()->Top();
2129 Node* receiver = environment()->Peek(1);
2130 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2131 VectorSlotPair pair =
2132 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2133 FrameStateBeforeAndAfter states(this, property->obj()->id());
2134 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2135 states.AddToNode(old_value, property->LoadId(),
2136 OutputFrameStateCombine::Push());
2137 break;
2138 }
2139 case KEYED_SUPER_PROPERTY: {
2140 Node* key = environment()->Top();
2141 Node* home_object = environment()->Peek(1);
2142 Node* receiver = environment()->Peek(2);
2143 VectorSlotPair pair =
2144 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2145 FrameStateBeforeAndAfter states(this, property->key()->id());
2146 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2147 states.AddToNode(old_value, property->LoadId(),
2148 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002149 break;
2150 }
2151 }
2152 environment()->Push(old_value);
2153 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 Node* value;
2155 {
2156 FrameStateBeforeAndAfter states(this, expr->value()->id());
2157 Node* right = environment()->Pop();
2158 Node* left = environment()->Pop();
2159 value =
2160 BuildBinaryOp(left, right, expr->binary_op(),
2161 expr->binary_operation()->BinaryOperationFeedbackId());
2162 states.AddToNode(value, expr->binary_operation()->id(),
2163 OutputFrameStateCombine::Push());
2164 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002165 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002166 if (needs_frame_state_before) {
2167 before_store_id = expr->binary_operation()->id();
2168 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002169 } else {
2170 VisitForValue(expr->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 if (needs_frame_state_before) {
2172 before_store_id = expr->value()->id();
2173 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002174 }
2175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002176 FrameStateBeforeAndAfter store_states(this, before_store_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002177 // Store the value.
2178 Node* value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002179 VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002180 switch (assign_type) {
2181 case VARIABLE: {
2182 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002183 BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2184 store_states, ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002185 break;
2186 }
2187 case NAMED_PROPERTY: {
2188 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002189 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2190 Node* store = BuildNamedStore(object, name, value, feedback);
2191 store_states.AddToNode(store, expr->id(),
2192 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002193 break;
2194 }
2195 case KEYED_PROPERTY: {
2196 Node* key = environment()->Pop();
2197 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002198 Node* store = BuildKeyedStore(object, key, value, feedback);
2199 store_states.AddToNode(store, expr->id(),
2200 ast_context()->GetStateCombine());
2201 break;
2202 }
2203 case NAMED_SUPER_PROPERTY: {
2204 Node* home_object = environment()->Pop();
2205 Node* receiver = environment()->Pop();
2206 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2207 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2208 store_states.AddToNode(store, expr->id(),
2209 ast_context()->GetStateCombine());
2210 break;
2211 }
2212 case KEYED_SUPER_PROPERTY: {
2213 Node* key = environment()->Pop();
2214 Node* home_object = environment()->Pop();
2215 Node* receiver = environment()->Pop();
2216 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2217 store_states.AddToNode(store, expr->id(),
2218 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 break;
2220 }
2221 }
2222
2223 ast_context()->ProduceValue(value);
2224}
2225
2226
2227void AstGraphBuilder::VisitYield(Yield* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002228 // TODO(turbofan): Implement yield here.
2229 SetStackOverflow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002230 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2231}
2232
2233
2234void AstGraphBuilder::VisitThrow(Throw* expr) {
2235 VisitForValue(expr->exception());
2236 Node* exception = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002237 Node* value = BuildThrowError(exception, expr->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002238 ast_context()->ProduceValue(value);
2239}
2240
2241
2242void AstGraphBuilder::VisitProperty(Property* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002243 Node* value = nullptr;
2244 LhsKind property_kind = Property::GetAssignType(expr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002245 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002246 switch (property_kind) {
2247 case VARIABLE:
2248 UNREACHABLE();
2249 break;
2250 case NAMED_PROPERTY: {
2251 VisitForValue(expr->obj());
2252 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2253 Node* object = environment()->Pop();
2254 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2255 value = BuildNamedLoad(object, name, pair);
2256 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2257 break;
2258 }
2259 case KEYED_PROPERTY: {
2260 VisitForValue(expr->obj());
2261 VisitForValue(expr->key());
2262 FrameStateBeforeAndAfter states(this, expr->key()->id());
2263 Node* key = environment()->Pop();
2264 Node* object = environment()->Pop();
2265 value = BuildKeyedLoad(object, key, pair);
2266 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2267 break;
2268 }
2269 case NAMED_SUPER_PROPERTY: {
2270 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2271 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2272 FrameStateBeforeAndAfter states(this, expr->obj()->id());
2273 Node* home_object = environment()->Pop();
2274 Node* receiver = environment()->Pop();
2275 Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2276 value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2277 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2278 break;
2279 }
2280 case KEYED_SUPER_PROPERTY: {
2281 VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2282 VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2283 VisitForValue(expr->key());
2284 FrameStateBeforeAndAfter states(this, expr->key()->id());
2285 Node* key = environment()->Pop();
2286 Node* home_object = environment()->Pop();
2287 Node* receiver = environment()->Pop();
2288 value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2289 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2290 break;
2291 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002292 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002293 ast_context()->ProduceValue(value);
2294}
2295
2296
2297void AstGraphBuilder::VisitCall(Call* expr) {
2298 Expression* callee = expr->expression();
2299 Call::CallType call_type = expr->GetCallType(isolate());
2300
2301 // Prepare the callee and the receiver to the function call. This depends on
2302 // the semantics of the underlying call type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002303 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2304 Node* receiver_value = nullptr;
2305 Node* callee_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002306 bool possibly_eval = false;
2307 switch (call_type) {
2308 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002309 VariableProxy* proxy = callee->AsVariableProxy();
2310 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002311 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002312 callee_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002313 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2314 pair, OutputFrameStateCombine::Push());
2315 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002316 receiver_value = jsgraph()->UndefinedConstant();
2317 break;
2318 }
2319 case Call::LOOKUP_SLOT_CALL: {
2320 Variable* variable = callee->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002321 DCHECK(variable->location() == VariableLocation::LOOKUP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002322 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002323 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002324 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2325 Node* pair = NewNode(op, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002326 callee_value = NewNode(common()->Projection(0), pair);
2327 receiver_value = NewNode(common()->Projection(1), pair);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002328 PrepareFrameState(pair, expr->LookupId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002329 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002330 break;
2331 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002332 case Call::NAMED_PROPERTY_CALL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002333 Property* property = callee->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002334 VectorSlotPair feedback =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002335 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002336 VisitForValue(property->obj());
2337 FrameStateBeforeAndAfter states(this, property->obj()->id());
2338 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2339 Node* object = environment()->Top();
2340 callee_value = BuildNamedLoad(object, name, feedback);
2341 states.AddToNode(callee_value, property->LoadId(),
2342 OutputFrameStateCombine::Push());
2343 // Note that a property call requires the receiver to be wrapped into
2344 // an object for sloppy callees. However the receiver is guaranteed
2345 // not to be null or undefined at this point.
2346 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 receiver_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002348 break;
2349 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 case Call::KEYED_PROPERTY_CALL: {
2351 Property* property = callee->AsProperty();
2352 VectorSlotPair feedback =
2353 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2354 VisitForValue(property->obj());
2355 VisitForValue(property->key());
2356 FrameStateBeforeAndAfter states(this, property->key()->id());
2357 Node* key = environment()->Pop();
2358 Node* object = environment()->Top();
2359 callee_value = BuildKeyedLoad(object, key, feedback);
2360 states.AddToNode(callee_value, property->LoadId(),
2361 OutputFrameStateCombine::Push());
2362 // Note that a property call requires the receiver to be wrapped into
2363 // an object for sloppy callees. However the receiver is guaranteed
2364 // not to be null or undefined at this point.
2365 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2366 receiver_value = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002367 break;
2368 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002369 case Call::NAMED_SUPER_PROPERTY_CALL: {
2370 Property* property = callee->AsProperty();
2371 SuperPropertyReference* super_ref =
2372 property->obj()->AsSuperPropertyReference();
2373 VisitForValue(super_ref->home_object());
2374 VisitForValue(super_ref->this_var());
2375 Node* home = environment()->Peek(1);
2376 Node* object = environment()->Top();
2377 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2378 FrameStateBeforeAndAfter states(this, property->obj()->id());
2379 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
2380 states.AddToNode(callee_value, property->LoadId(),
2381 OutputFrameStateCombine::Push());
2382 // Note that a property call requires the receiver to be wrapped into
2383 // an object for sloppy callees. Since the receiver is not the target of
2384 // the load, it could very well be null or undefined at this point.
2385 receiver_value = environment()->Pop();
2386 environment()->Drop(1);
2387 break;
2388 }
2389 case Call::KEYED_SUPER_PROPERTY_CALL: {
2390 Property* property = callee->AsProperty();
2391 SuperPropertyReference* super_ref =
2392 property->obj()->AsSuperPropertyReference();
2393 VisitForValue(super_ref->home_object());
2394 VisitForValue(super_ref->this_var());
2395 environment()->Push(environment()->Top()); // Duplicate this_var.
2396 environment()->Push(environment()->Peek(2)); // Duplicate home_obj.
2397 VisitForValue(property->key());
2398 Node* key = environment()->Pop();
2399 Node* home = environment()->Pop();
2400 Node* object = environment()->Pop();
2401 FrameStateBeforeAndAfter states(this, property->key()->id());
2402 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
2403 states.AddToNode(callee_value, property->LoadId(),
2404 OutputFrameStateCombine::Push());
2405 // Note that a property call requires the receiver to be wrapped into
2406 // an object for sloppy callees. Since the receiver is not the target of
2407 // the load, it could very well be null or undefined at this point.
2408 receiver_value = environment()->Pop();
2409 environment()->Drop(1);
2410 break;
2411 }
2412 case Call::SUPER_CALL:
2413 return VisitCallSuper(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002414 case Call::POSSIBLY_EVAL_CALL:
2415 possibly_eval = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002416 if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2417 Variable* variable = callee->AsVariableProxy()->var();
2418 Node* name = jsgraph()->Constant(variable->name());
2419 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002420 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2421 Node* pair = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002422 callee_value = NewNode(common()->Projection(0), pair);
2423 receiver_value = NewNode(common()->Projection(1), pair);
2424 PrepareFrameState(pair, expr->LookupId(),
2425 OutputFrameStateCombine::Push(2));
2426 break;
2427 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002428 // Fall through.
2429 case Call::OTHER_CALL:
2430 VisitForValue(callee);
2431 callee_value = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 receiver_hint = ConvertReceiverMode::kNullOrUndefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002433 receiver_value = jsgraph()->UndefinedConstant();
2434 break;
2435 }
2436
2437 // The callee and the receiver both have to be pushed onto the operand stack
2438 // before arguments are being evaluated.
2439 environment()->Push(callee_value);
2440 environment()->Push(receiver_value);
2441
2442 // Evaluate all arguments to the function call,
2443 ZoneList<Expression*>* args = expr->arguments();
2444 VisitForValues(args);
2445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002446 // Resolve callee for a potential direct eval call. This block will mutate the
2447 // callee value pushed onto the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002448 if (possibly_eval && args->length() > 0) {
2449 int arg_count = args->length();
2450
2451 // Extract callee and source string from the environment.
2452 Node* callee = environment()->Peek(arg_count + 1);
2453 Node* source = environment()->Peek(arg_count - 1);
2454
2455 // Create node to ask for help resolving potential eval call. This will
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002456 // provide a fully resolved callee to patch into the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002457 Node* function = GetFunctionClosure();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002458 Node* language = jsgraph()->Constant(language_mode());
2459 Node* position = jsgraph()->Constant(current_scope()->start_position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002460 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002461 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002462 Node* new_callee =
2463 NewNode(op, callee, source, function, language, position);
2464 PrepareFrameState(new_callee, expr->EvalId(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002465 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467 // Patch callee on the environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 environment()->Poke(arg_count + 1, new_callee);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002469 }
2470
2471 // Create node to perform the function call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002472 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2473 const Operator* call = javascript()->CallFunction(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002474 args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002475 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002476 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002477 environment()->Push(value->InputAt(0)); // The callee passed to the call.
2478 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2479 environment()->Drop(1);
2480 ast_context()->ProduceValue(value);
2481}
2482
2483
2484void AstGraphBuilder::VisitCallSuper(Call* expr) {
2485 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2486 DCHECK_NOT_NULL(super);
2487
2488 // Prepare the callee to the super call.
2489 VisitForValue(super->this_function_var());
2490 Node* this_function = environment()->Pop();
2491 const Operator* op =
2492 javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2493 Node* super_function = NewNode(op, this_function);
2494 environment()->Push(super_function);
2495
2496 // Evaluate all arguments to the super call.
2497 ZoneList<Expression*>* args = expr->arguments();
2498 VisitForValues(args);
2499
2500 // The new target is loaded from the {new.target} variable.
2501 VisitForValue(super->new_target_var());
2502
2503 // Create node to perform the super call.
2504 const Operator* call =
2505 javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
2506 FrameStateBeforeAndAfter states(this, super->new_target_var()->id());
2507 Node* value = ProcessArguments(call, args->length() + 2);
2508 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002509 ast_context()->ProduceValue(value);
2510}
2511
2512
2513void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2514 VisitForValue(expr->expression());
2515
2516 // Evaluate all arguments to the construct call.
2517 ZoneList<Expression*>* args = expr->arguments();
2518 VisitForValues(args);
2519
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002520 // The baseline compiler doesn't push the new.target, so we need to record
2521 // the frame state before the push.
2522 FrameStateBeforeAndAfter states(
2523 this, args->is_empty() ? expr->expression()->id() : args->last()->id());
2524
2525 // The new target is the same as the callee.
2526 environment()->Push(environment()->Peek(args->length()));
2527
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002528 // Create node to perform the construct call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002529 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2530 const Operator* call =
2531 javascript()->CallConstruct(args->length() + 2, feedback);
2532 Node* value = ProcessArguments(call, args->length() + 2);
2533 states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002534 ast_context()->ProduceValue(value);
2535}
2536
2537
2538void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002539 // The callee and the receiver both have to be pushed onto the operand stack
2540 // before arguments are being evaluated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2542 Node* receiver_value = jsgraph()->UndefinedConstant();
2543
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544 environment()->Push(callee_value);
2545 environment()->Push(receiver_value);
2546
2547 // Evaluate all arguments to the JS runtime call.
2548 ZoneList<Expression*>* args = expr->arguments();
2549 VisitForValues(args);
2550
2551 // Create node to perform the JS runtime call.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002552 const Operator* call = javascript()->CallFunction(args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002553 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002554 Node* value = ProcessArguments(call, args->length() + 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002555 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556 ast_context()->ProduceValue(value);
2557}
2558
2559
2560void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002561 // Handle calls to runtime functions implemented in JavaScript separately as
2562 // the call follows JavaScript ABI and the callee is statically unknown.
2563 if (expr->is_jsruntime()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002564 return VisitCallJSRuntime(expr);
2565 }
2566
2567 // Evaluate all arguments to the runtime call.
2568 ZoneList<Expression*>* args = expr->arguments();
2569 VisitForValues(args);
2570
2571 // Create node to perform the runtime call.
Ben Murdochda12d292016-06-02 14:46:10 +01002572 Runtime::FunctionId functionId = expr->function()->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002573 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574 FrameStateBeforeAndAfter states(this, expr->CallId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002575 Node* value = ProcessArguments(call, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002576 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002577 ast_context()->ProduceValue(value);
2578}
2579
2580
2581void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2582 switch (expr->op()) {
2583 case Token::DELETE:
2584 return VisitDelete(expr);
2585 case Token::VOID:
2586 return VisitVoid(expr);
2587 case Token::TYPEOF:
2588 return VisitTypeof(expr);
2589 case Token::NOT:
2590 return VisitNot(expr);
2591 default:
2592 UNREACHABLE();
2593 }
2594}
2595
2596
2597void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002599
2600 // Left-hand side can only be a property, a global or a variable slot.
2601 Property* property = expr->expression()->AsProperty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 LhsKind assign_type = Property::GetAssignType(property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603
2604 // Reserve space for result of postfix operation.
2605 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 if (is_postfix && assign_type != VARIABLE) {
2607 environment()->Push(jsgraph()->ZeroConstant());
2608 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002609
2610 // Evaluate LHS expression and get old value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002611 Node* old_value = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002612 int stack_depth = -1;
2613 switch (assign_type) {
2614 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002615 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2616 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002617 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002618 old_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002619 BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2620 pair, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002621 stack_depth = 0;
2622 break;
2623 }
2624 case NAMED_PROPERTY: {
2625 VisitForValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 FrameStateBeforeAndAfter states(this, property->obj()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627 Node* object = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002628 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002629 VectorSlotPair pair =
2630 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002631 old_value = BuildNamedLoad(object, name, pair);
2632 states.AddToNode(old_value, property->LoadId(),
2633 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002634 stack_depth = 1;
2635 break;
2636 }
2637 case KEYED_PROPERTY: {
2638 VisitForValue(property->obj());
2639 VisitForValue(property->key());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002640 FrameStateBeforeAndAfter states(this, property->key()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002641 Node* key = environment()->Top();
2642 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002643 VectorSlotPair pair =
2644 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002645 old_value = BuildKeyedLoad(object, key, pair);
2646 states.AddToNode(old_value, property->LoadId(),
2647 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002648 stack_depth = 2;
2649 break;
2650 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002651 case NAMED_SUPER_PROPERTY: {
2652 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2653 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2654 FrameStateBeforeAndAfter states(this, property->obj()->id());
2655 Node* home_object = environment()->Top();
2656 Node* receiver = environment()->Peek(1);
2657 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2658 VectorSlotPair pair =
2659 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2660 old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2661 states.AddToNode(old_value, property->LoadId(),
2662 OutputFrameStateCombine::Push());
2663 stack_depth = 2;
2664 break;
2665 }
2666 case KEYED_SUPER_PROPERTY: {
2667 VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2668 VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2669 VisitForValue(property->key());
2670 FrameStateBeforeAndAfter states(this, property->obj()->id());
2671 Node* key = environment()->Top();
2672 Node* home_object = environment()->Peek(1);
2673 Node* receiver = environment()->Peek(2);
2674 VectorSlotPair pair =
2675 CreateVectorSlotPair(property->PropertyFeedbackSlot());
2676 old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2677 states.AddToNode(old_value, property->LoadId(),
2678 OutputFrameStateCombine::Push());
2679 stack_depth = 3;
2680 break;
2681 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002682 }
2683
2684 // Convert old value into a number.
Ben Murdochda12d292016-06-02 14:46:10 +01002685 old_value = NewNode(javascript()->ToNumber(), old_value);
2686 PrepareFrameState(old_value, expr->ToNumberId(),
2687 OutputFrameStateCombine::Push());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002688
2689 // Create a proper eager frame state for the stores.
2690 environment()->Push(old_value);
2691 FrameStateBeforeAndAfter store_states(this, expr->ToNumberId());
2692 old_value = environment()->Pop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002693
2694 // Save result for postfix expressions at correct stack depth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002695 if (is_postfix) {
2696 if (assign_type != VARIABLE) {
2697 environment()->Poke(stack_depth, old_value);
2698 } else {
2699 environment()->Push(old_value);
2700 }
2701 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002702
2703 // Create node to perform +1/-1 operation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002704 Node* value;
2705 {
2706 // TODO(bmeurer): Cleanup this feedback/bailout mess!
2707 FrameStateBeforeAndAfter states(this, BailoutId::None());
2708 value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002709 expr->binary_op(), expr->CountBinOpFeedbackId());
Ben Murdochda12d292016-06-02 14:46:10 +01002710 // This should never deoptimize because we have converted to number before.
2711 states.AddToNode(value, BailoutId::None(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002712 OutputFrameStateCombine::Ignore());
2713 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002714
2715 // Store the value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002716 VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002717 switch (assign_type) {
2718 case VARIABLE: {
2719 Variable* variable = expr->expression()->AsVariableProxy()->var();
2720 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002721 BuildVariableAssignment(variable, value, expr->op(), feedback,
2722 expr->AssignmentId(), store_states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002723 environment()->Pop();
2724 break;
2725 }
2726 case NAMED_PROPERTY: {
2727 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002728 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2729 Node* store = BuildNamedStore(object, name, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002730 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002731 store_states.AddToNode(store, expr->AssignmentId(),
2732 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002733 environment()->Pop();
2734 break;
2735 }
2736 case KEYED_PROPERTY: {
2737 Node* key = environment()->Pop();
2738 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002739 Node* store = BuildKeyedStore(object, key, value, feedback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002740 environment()->Push(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002741 store_states.AddToNode(store, expr->AssignmentId(),
2742 OutputFrameStateCombine::Ignore());
2743 environment()->Pop();
2744 break;
2745 }
2746 case NAMED_SUPER_PROPERTY: {
2747 Node* home_object = environment()->Pop();
2748 Node* receiver = environment()->Pop();
2749 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2750 Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2751 environment()->Push(value);
2752 store_states.AddToNode(store, expr->AssignmentId(),
2753 OutputFrameStateCombine::Ignore());
2754 environment()->Pop();
2755 break;
2756 }
2757 case KEYED_SUPER_PROPERTY: {
2758 Node* key = environment()->Pop();
2759 Node* home_object = environment()->Pop();
2760 Node* receiver = environment()->Pop();
2761 Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2762 environment()->Push(value);
2763 store_states.AddToNode(store, expr->AssignmentId(),
2764 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002765 environment()->Pop();
2766 break;
2767 }
2768 }
2769
2770 // Restore old value for postfix expressions.
2771 if (is_postfix) value = environment()->Pop();
2772
2773 ast_context()->ProduceValue(value);
2774}
2775
2776
2777void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2778 switch (expr->op()) {
2779 case Token::COMMA:
2780 return VisitComma(expr);
2781 case Token::OR:
2782 case Token::AND:
2783 return VisitLogicalExpression(expr);
2784 default: {
2785 VisitForValue(expr->left());
2786 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002787 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002788 Node* right = environment()->Pop();
2789 Node* left = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002790 Node* value = BuildBinaryOp(left, right, expr->op(),
2791 expr->BinaryOperationFeedbackId());
2792 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002793 ast_context()->ProduceValue(value);
2794 }
2795 }
2796}
2797
Ben Murdochda12d292016-06-02 14:46:10 +01002798void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
2799 Expression* sub_expr,
2800 Node* nil_value) {
2801 const Operator* op = nullptr;
2802 switch (expr->op()) {
2803 case Token::EQ:
2804 op = javascript()->Equal();
2805 break;
2806 case Token::EQ_STRICT:
2807 op = javascript()->StrictEqual();
2808 break;
2809 default:
2810 UNREACHABLE();
2811 }
2812 VisitForValue(sub_expr);
2813 FrameStateBeforeAndAfter states(this, sub_expr->id());
2814 Node* value_to_compare = environment()->Pop();
2815 Node* value = NewNode(op, value_to_compare, nil_value);
2816 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2817 return ast_context()->ProduceValue(value);
2818}
2819
2820void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
2821 Expression* sub_expr,
2822 Handle<String> check) {
2823 VisitTypeofExpression(sub_expr);
2824 FrameStateBeforeAndAfter states(this, sub_expr->id());
2825 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
2826 Node* value = NewNode(javascript()->StrictEqual(), typeof_arg,
2827 jsgraph()->Constant(check));
2828 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2829 return ast_context()->ProduceValue(value);
2830}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002831
2832void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Ben Murdochda12d292016-06-02 14:46:10 +01002833 // Check for a few fast cases. The AST visiting behavior must be in sync
2834 // with the full codegen: We don't push both left and right values onto
2835 // the expression stack when one side is a special-case literal.
2836 Expression* sub_expr = nullptr;
2837 Handle<String> check;
2838 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
2839 return VisitLiteralCompareTypeof(expr, sub_expr, check);
2840 }
2841 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
2842 return VisitLiteralCompareNil(expr, sub_expr,
2843 jsgraph()->UndefinedConstant());
2844 }
2845 if (expr->IsLiteralCompareNull(&sub_expr)) {
2846 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
2847 }
2848
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002849 const Operator* op;
2850 switch (expr->op()) {
2851 case Token::EQ:
2852 op = javascript()->Equal();
2853 break;
2854 case Token::NE:
2855 op = javascript()->NotEqual();
2856 break;
2857 case Token::EQ_STRICT:
2858 op = javascript()->StrictEqual();
2859 break;
2860 case Token::NE_STRICT:
2861 op = javascript()->StrictNotEqual();
2862 break;
2863 case Token::LT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002864 op = javascript()->LessThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002865 break;
2866 case Token::GT:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002867 op = javascript()->GreaterThan();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002868 break;
2869 case Token::LTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002870 op = javascript()->LessThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002871 break;
2872 case Token::GTE:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002873 op = javascript()->GreaterThanOrEqual();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002874 break;
2875 case Token::INSTANCEOF:
Ben Murdochda12d292016-06-02 14:46:10 +01002876 DCHECK(!FLAG_harmony_instanceof);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002877 op = javascript()->InstanceOf();
2878 break;
2879 case Token::IN:
2880 op = javascript()->HasProperty();
2881 break;
2882 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002883 op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002884 UNREACHABLE();
2885 }
2886 VisitForValue(expr->left());
2887 VisitForValue(expr->right());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002888 FrameStateBeforeAndAfter states(this, expr->right()->id());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002889 Node* right = environment()->Pop();
2890 Node* left = environment()->Pop();
2891 Node* value = NewNode(op, left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002892 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002893 ast_context()->ProduceValue(value);
2894}
2895
2896
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002897void AstGraphBuilder::VisitSpread(Spread* expr) {
2898 // Handled entirely by the parser itself.
2899 UNREACHABLE();
2900}
2901
2902
2903void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2904 // Handled entirely by the parser itself.
2905 UNREACHABLE();
2906}
2907
2908
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002909void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2910 Node* value = GetFunctionClosure();
2911 ast_context()->ProduceValue(value);
2912}
2913
2914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002915void AstGraphBuilder::VisitSuperPropertyReference(
2916 SuperPropertyReference* expr) {
2917 Node* value = BuildThrowUnsupportedSuperError(expr->id());
2918 ast_context()->ProduceValue(value);
2919}
2920
2921
2922void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2923 // Handled by VisitCall
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002924 UNREACHABLE();
2925}
2926
2927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002928void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2929 // Handled entirely in VisitSwitch.
2930 UNREACHABLE();
2931}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002932
2933
2934void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002935 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002936 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002937 if (globals()->empty()) return;
2938 int array_index = 0;
2939 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2940 static_cast<int>(globals()->size()), TENURED);
2941 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002942 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
2943 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002944 DeclareGlobalsLanguageMode::encode(language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002945 Node* flags = jsgraph()->Constant(encoded_flags);
2946 Node* pairs = jsgraph()->Constant(data);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002947 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002948 Node* call = NewNode(op, pairs, flags);
2949 PrepareFrameState(call, BailoutId::Declarations());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002950 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002951}
2952
2953
2954void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002955 if (stmt == nullptr) return;
2956 Visit(stmt);
2957}
2958
2959
2960void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2961 ContextScope scope(this, s, context);
2962 DCHECK(s->declarations()->is_empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002963 Visit(stmt);
2964}
2965
2966
2967void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002968 LoopBuilder* loop) {
2969 ControlScopeForIteration scope(this, stmt, loop);
2970 if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
2971 Node* node = NewNode(javascript()->StackCheck());
2972 PrepareFrameState(node, stmt->StackCheckId());
2973 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002974 Visit(stmt->body());
2975}
2976
2977
2978void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2979 Node* value;
2980 if (expr->expression()->IsVariableProxy()) {
2981 // Delete of an unqualified identifier is only allowed in classic mode but
2982 // deleting "this" is allowed in all language modes.
2983 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002984 // Delete of an unqualified identifier is disallowed in strict mode but
2985 // "delete this" is allowed.
2986 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002987 value = BuildVariableDelete(variable, expr->id(),
2988 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002989 } else if (expr->expression()->IsProperty()) {
2990 Property* property = expr->expression()->AsProperty();
2991 VisitForValue(property->obj());
2992 VisitForValue(property->key());
2993 Node* key = environment()->Pop();
2994 Node* object = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002995 value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002996 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002997 } else {
2998 VisitForEffect(expr->expression());
2999 value = jsgraph()->TrueConstant();
3000 }
3001 ast_context()->ProduceValue(value);
3002}
3003
3004
3005void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
3006 VisitForEffect(expr->expression());
3007 Node* value = jsgraph()->UndefinedConstant();
3008 ast_context()->ProduceValue(value);
3009}
3010
Ben Murdochda12d292016-06-02 14:46:10 +01003011void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
3012 if (expr->IsVariableProxy()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003013 // Typeof does not throw a reference error on global variables, hence we
3014 // perform a non-contextual load in case the operand is a variable proxy.
Ben Murdochda12d292016-06-02 14:46:10 +01003015 VariableProxy* proxy = expr->AsVariableProxy();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003016 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003017 FrameStateBeforeAndAfter states(this, BeforeId(proxy));
Ben Murdochda12d292016-06-02 14:46:10 +01003018 Node* load =
3019 BuildVariableLoad(proxy->var(), expr->id(), states, pair,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003020 OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Ben Murdochda12d292016-06-02 14:46:10 +01003021 environment()->Push(load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003022 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01003023 VisitForValue(expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003024 }
Ben Murdochda12d292016-06-02 14:46:10 +01003025}
3026
3027void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
3028 VisitTypeofExpression(expr->expression());
3029 Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003030 ast_context()->ProduceValue(value);
3031}
3032
3033
3034void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3035 VisitForValue(expr->expression());
3036 Node* operand = environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003037 Node* input = BuildToBoolean(operand, expr->expression()->test_id());
3038 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
3039 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003040 ast_context()->ProduceValue(value);
3041}
3042
3043
3044void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3045 VisitForEffect(expr->left());
3046 Visit(expr->right());
3047 ast_context()->ReplaceValue();
3048}
3049
3050
3051void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3052 bool is_logical_and = expr->op() == Token::AND;
3053 IfBuilder compare_if(this);
3054 VisitForValue(expr->left());
3055 Node* condition = environment()->Top();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003056 compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003057 compare_if.Then();
3058 if (is_logical_and) {
3059 environment()->Pop();
3060 Visit(expr->right());
3061 } else if (ast_context()->IsEffect()) {
3062 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003063 } else if (ast_context()->IsTest()) {
3064 environment()->Poke(0, jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003065 }
3066 compare_if.Else();
3067 if (!is_logical_and) {
3068 environment()->Pop();
3069 Visit(expr->right());
3070 } else if (ast_context()->IsEffect()) {
3071 environment()->Pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003072 } else if (ast_context()->IsTest()) {
3073 environment()->Poke(0, jsgraph()->FalseConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003074 }
3075 compare_if.End();
3076 ast_context()->ReplaceValue();
3077}
3078
3079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003080LanguageMode AstGraphBuilder::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003081 return current_scope()->language_mode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003082}
3083
3084
3085VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003086 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003087 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3088}
3089
3090
Ben Murdoch097c5b22016-05-18 11:27:45 +01003091void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003092 Visit(node->expression());
3093}
3094
3095
3096namespace {
3097
3098// Limit of context chain length to which inline check is possible.
3099const int kMaxCheckDepth = 30;
3100
3101// Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3102const uint32_t kFullCheckRequired = -1;
3103
3104} // namespace
3105
3106
3107uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3108 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3109 bool found_eval_scope = false;
3110 uint32_t check_depths = 0;
3111 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3112 if (s->num_heap_slots() <= 0) continue;
3113 // TODO(mstarzinger): If we have reached an eval scope, we check all
3114 // extensions from this point. Replicated from full-codegen, figure out
3115 // whether this is still needed. If not, drop {found_eval_scope} below.
3116 if (s->is_eval_scope()) found_eval_scope = true;
3117 if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3118 int depth = current_scope()->ContextChainLength(s);
3119 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3120 check_depths |= 1 << depth;
3121 }
3122 return check_depths;
3123}
3124
3125
3126uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3127 DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3128 uint32_t check_depths = 0;
3129 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3130 if (s->num_heap_slots() <= 0) continue;
3131 if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3132 int depth = current_scope()->ContextChainLength(s);
3133 if (depth > kMaxCheckDepth) return kFullCheckRequired;
3134 check_depths |= 1 << depth;
3135 if (s == variable->scope()) break;
3136 }
3137 return check_depths;
3138}
3139
3140
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003141Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3142 DCHECK(environment()->stack_height() >= arity);
3143 Node** all = info()->zone()->NewArray<Node*>(arity);
3144 for (int i = arity - 1; i >= 0; --i) {
3145 all[i] = environment()->Pop();
3146 }
3147 Node* value = NewNode(op, arity, all);
3148 return value;
3149}
3150
3151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003152Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3153 Scope* scope = info()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003154
3155 // Allocate a new local context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003156 Node* local_context = scope->is_script_scope()
3157 ? BuildLocalScriptContext(scope)
3158 : BuildLocalFunctionContext(scope);
3159
3160 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3161 Node* receiver = environment()->RawParameterLookup(0);
3162 // Context variable (at bottom of the context chain).
3163 Variable* variable = scope->receiver();
3164 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3165 const Operator* op = javascript()->StoreContext(0, variable->index());
3166 NewNode(op, local_context, receiver);
3167 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003168
3169 // Copy parameters into context if necessary.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003170 int num_parameters = scope->num_parameters();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003171 for (int i = 0; i < num_parameters; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003172 Variable* variable = scope->parameter(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003173 if (!variable->IsContextSlot()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003174 Node* parameter = environment()->RawParameterLookup(i + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003175 // Context variable (at bottom of the context chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003176 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003177 const Operator* op = javascript()->StoreContext(0, variable->index());
3178 NewNode(op, local_context, parameter);
3179 }
3180
3181 return local_context;
3182}
3183
3184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003185Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
3186 DCHECK(scope->is_function_scope());
3187
3188 // Allocate a new local context.
3189 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3190 const Operator* op = javascript()->CreateFunctionContext(slot_count);
3191 Node* local_context = NewNode(op, GetFunctionClosure());
3192
3193 return local_context;
3194}
3195
3196
3197Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3198 DCHECK(scope->is_script_scope());
3199
3200 // Allocate a new local context.
3201 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3202 const Operator* op = javascript()->CreateScriptContext(scope_info);
3203 Node* local_context = NewNode(op, GetFunctionClosure());
3204 PrepareFrameState(local_context, BailoutId::ScriptContext(),
3205 OutputFrameStateCombine::Push());
3206
3207 return local_context;
3208}
3209
3210
3211Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3212 DCHECK(scope->is_block_scope());
3213
3214 // Allocate a new local context.
3215 Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
3216 const Operator* op = javascript()->CreateBlockContext(scope_info);
3217 Node* local_context = NewNode(op, GetFunctionClosureForContext());
3218
3219 return local_context;
3220}
3221
3222
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003223Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003224 if (arguments == nullptr) return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003225
3226 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003227 CreateArgumentsType type =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003228 is_strict(language_mode()) || !info()->has_simple_parameters()
Ben Murdoch097c5b22016-05-18 11:27:45 +01003229 ? CreateArgumentsType::kUnmappedArguments
3230 : CreateArgumentsType::kMappedArguments;
3231 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003232 Node* object = NewNode(op, GetFunctionClosure());
3233 PrepareFrameState(object, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003235 // Assign the object to the {arguments} variable. This should never lazy
3236 // deopt, so it is fine to send invalid bailout id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003237 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003238 FrameStateBeforeAndAfter states(this, BailoutId::None());
3239 BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3240 BailoutId::None(), states);
3241 return object;
3242}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003244
3245Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3246 if (rest == nullptr) return nullptr;
3247
3248 // Allocate and initialize a new arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003249 CreateArgumentsType type = CreateArgumentsType::kRestParameter;
3250 const Operator* op = javascript()->CreateArguments(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003251 Node* object = NewNode(op, GetFunctionClosure());
3252 PrepareFrameState(object, BailoutId::None());
3253
3254 // Assign the object to the {rest} variable. This should never lazy
3255 // deopt, so it is fine to send invalid bailout id.
3256 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3257 FrameStateBeforeAndAfter states(this, BailoutId::None());
3258 BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3259 BailoutId::None(), states);
3260 return object;
3261}
3262
3263
3264Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3265 if (this_function_var == nullptr) return nullptr;
3266
3267 // Retrieve the closure we were called with.
3268 Node* this_function = GetFunctionClosure();
3269
3270 // Assign the object to the {.this_function} variable. This should never lazy
3271 // deopt, so it is fine to send invalid bailout id.
3272 FrameStateBeforeAndAfter states(this, BailoutId::None());
3273 BuildVariableAssignment(this_function_var, this_function, Token::INIT,
3274 VectorSlotPair(), BailoutId::None(), states);
3275 return this_function;
3276}
3277
3278
3279Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3280 if (new_target_var == nullptr) return nullptr;
3281
3282 // Retrieve the new target we were called with.
3283 Node* object = GetNewTarget();
3284
3285 // Assign the object to the {new.target} variable. This should never lazy
3286 // deopt, so it is fine to send invalid bailout id.
3287 FrameStateBeforeAndAfter states(this, BailoutId::None());
3288 BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
3289 BailoutId::None(), states);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003290 return object;
3291}
3292
3293
3294Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
3295 Node* not_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003296 Node* the_hole = jsgraph()->TheHoleConstant();
3297 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3298 return NewNode(
3299 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
3300 check, for_hole, not_hole);
3301}
3302
3303
3304Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3305 Node* not_hole,
3306 BailoutId bailout_id) {
3307 IfBuilder hole_check(this);
3308 Node* the_hole = jsgraph()->TheHoleConstant();
3309 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3310 hole_check.If(check);
3311 hole_check.Then();
3312 Node* error = BuildThrowReferenceError(variable, bailout_id);
3313 environment()->Push(error);
3314 hole_check.Else();
3315 environment()->Push(not_hole);
3316 hole_check.End();
3317 return environment()->Pop();
3318}
3319
3320
3321Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3322 Node* for_hole,
3323 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003324 IfBuilder hole_check(this);
3325 Node* the_hole = jsgraph()->TheHoleConstant();
3326 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3327 hole_check.If(check);
3328 hole_check.Then();
3329 environment()->Push(for_hole);
3330 hole_check.Else();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003331 Node* error = BuildThrowReferenceError(variable, bailout_id);
3332 environment()->Push(error);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003333 hole_check.End();
3334 return environment()->Pop();
3335}
3336
3337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003338Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3339 BailoutId bailout_id) {
3340 IfBuilder prototype_check(this);
3341 Node* prototype_string =
3342 jsgraph()->Constant(isolate()->factory()->prototype_string());
3343 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
3344 prototype_check.If(check);
3345 prototype_check.Then();
3346 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3347 environment()->Push(error);
3348 prototype_check.Else();
3349 environment()->Push(name);
3350 prototype_check.End();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351 return environment()->Pop();
3352}
3353
3354
3355Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3356 BailoutId bailout_id,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003357 FrameStateBeforeAndAfter& states,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003358 const VectorSlotPair& feedback,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003359 OutputFrameStateCombine combine,
3360 TypeofMode typeof_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003361 Node* the_hole = jsgraph()->TheHoleConstant();
3362 VariableMode mode = variable->mode();
3363 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003364 case VariableLocation::GLOBAL:
3365 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003366 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003367 Handle<Name> name = variable->name();
3368 if (Node* node = TryLoadGlobalConstant(name)) return node;
3369 Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
3370 states.AddToNode(value, bailout_id, combine);
3371 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003372 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003373 case VariableLocation::PARAMETER:
3374 case VariableLocation::LOCAL: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003375 // Local var, const, or let variable.
3376 Node* value = environment()->Lookup(variable);
3377 if (mode == CONST_LEGACY) {
3378 // Perform check for uninitialized legacy const variables.
3379 if (value->op() == the_hole->op()) {
3380 value = jsgraph()->UndefinedConstant();
3381 } else if (value->opcode() == IrOpcode::kPhi) {
3382 Node* undefined = jsgraph()->UndefinedConstant();
3383 value = BuildHoleCheckSilent(value, undefined, value);
3384 }
3385 } else if (mode == LET || mode == CONST) {
3386 // Perform check for uninitialized let/const variables.
3387 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003388 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003389 } else if (value->opcode() == IrOpcode::kPhi) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003390 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003391 }
3392 }
3393 return value;
3394 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003395 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003396 // Context variable (potentially up the context chain).
3397 int depth = current_scope()->ContextChainLength(variable->scope());
3398 bool immutable = variable->maybe_assigned() == kNotAssigned;
3399 const Operator* op =
3400 javascript()->LoadContext(depth, variable->index(), immutable);
3401 Node* value = NewNode(op, current_context());
3402 // TODO(titzer): initialization checks are redundant for already
3403 // initialized immutable context loads, but only specialization knows.
3404 // Maybe specializer should be a parameter to the graph builder?
3405 if (mode == CONST_LEGACY) {
3406 // Perform check for uninitialized legacy const variables.
3407 Node* undefined = jsgraph()->UndefinedConstant();
3408 value = BuildHoleCheckSilent(value, undefined, value);
3409 } else if (mode == LET || mode == CONST) {
3410 // Perform check for uninitialized let/const variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003411 value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003412 }
3413 return value;
3414 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003415 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003416 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003417 Handle<String> name = variable->name();
3418 if (Node* node =
3419 TryLoadDynamicVariable(variable, name, bailout_id, states,
3420 feedback, combine, typeof_mode)) {
3421 return node;
3422 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003423 Node* value = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003424 states.AddToNode(value, bailout_id, combine);
3425 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003426 }
3427 }
3428 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003429 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003430}
3431
3432
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003433Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3434 BailoutId bailout_id,
3435 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003436 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003437 case VariableLocation::GLOBAL:
3438 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003439 // Global var, const, or let variable.
3440 Node* global = BuildLoadGlobalObject();
3441 Node* name = jsgraph()->Constant(variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003442 const Operator* op = javascript()->DeleteProperty(language_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003443 Node* result = NewNode(op, global, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003444 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003445 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003446 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003447 case VariableLocation::PARAMETER:
3448 case VariableLocation::LOCAL:
3449 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003450 // Local var, const, or let variable or context variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003451 return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3452 }
3453 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003454 // Dynamic lookup of context variable (anywhere in the chain).
3455 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003456 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003457 javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
3458 Node* result = NewNode(op, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003459 PrepareFrameState(result, bailout_id, combine);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003460 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003461 }
3462 }
3463 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003464 return nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003465}
3466
3467
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003468Node* AstGraphBuilder::BuildVariableAssignment(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003469 Variable* variable, Node* value, Token::Value op,
3470 const VectorSlotPair& feedback, BailoutId bailout_id,
3471 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003472 Node* the_hole = jsgraph()->TheHoleConstant();
3473 VariableMode mode = variable->mode();
3474 switch (variable->location()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003475 case VariableLocation::GLOBAL:
3476 case VariableLocation::UNALLOCATED: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003477 // Global var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003478 Handle<Name> name = variable->name();
3479 Node* store = BuildGlobalStore(name, value, feedback);
3480 states.AddToNode(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003481 return store;
3482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003483 case VariableLocation::PARAMETER:
3484 case VariableLocation::LOCAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003485 // Local var, const, or let variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003486 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003487 // Perform an initialization check for legacy const variables.
3488 Node* current = environment()->Lookup(variable);
3489 if (current->op() != the_hole->op()) {
3490 value = BuildHoleCheckSilent(current, value, current);
3491 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003492 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3493 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003494 // - exception in strict mode.
3495 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003496 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003497 return BuildThrowConstAssignError(bailout_id);
3498 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003499 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003500 } else if (mode == LET && op == Token::INIT) {
3501 // No initialization check needed because scoping guarantees it. Note
3502 // that we still perform a lookup to keep the variable live, because
3503 // baseline code might contain debug code that inspects the variable.
3504 Node* current = environment()->Lookup(variable);
3505 CHECK_NOT_NULL(current);
3506 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003507 // Perform an initialization check for let declared variables.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003508 Node* current = environment()->Lookup(variable);
3509 if (current->op() == the_hole->op()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003510 return BuildThrowReferenceError(variable, bailout_id);
3511 } else if (current->opcode() == IrOpcode::kPhi) {
3512 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003513 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003514 } else if (mode == CONST && op == Token::INIT) {
3515 // Perform an initialization check for const {this} variables.
3516 // Note that the {this} variable is the only const variable being able
3517 // to trigger bind operations outside the TDZ, via {super} calls.
3518 Node* current = environment()->Lookup(variable);
3519 if (current->op() != the_hole->op() && variable->is_this()) {
3520 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3521 }
3522 } else if (mode == CONST && op != Token::INIT) {
3523 // Assignment to const is exception in all modes.
3524 Node* current = environment()->Lookup(variable);
3525 if (current->op() == the_hole->op()) {
3526 return BuildThrowReferenceError(variable, bailout_id);
3527 } else if (current->opcode() == IrOpcode::kPhi) {
3528 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3529 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003530 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003531 }
3532 environment()->Bind(variable, value);
3533 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003534 case VariableLocation::CONTEXT: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003535 // Context variable (potentially up the context chain).
3536 int depth = current_scope()->ContextChainLength(variable->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003537 if (mode == CONST_LEGACY && op == Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003538 // Perform an initialization check for legacy const variables.
3539 const Operator* op =
3540 javascript()->LoadContext(depth, variable->index(), false);
3541 Node* current = NewNode(op, current_context());
3542 value = BuildHoleCheckSilent(current, value, current);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003543 } else if (mode == CONST_LEGACY && op != Token::INIT) {
3544 // Non-initializing assignment to legacy const is
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003545 // - exception in strict mode.
3546 // - ignored in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003547 if (is_strict(language_mode())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003548 return BuildThrowConstAssignError(bailout_id);
3549 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003550 return value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003551 } else if (mode == LET && op != Token::INIT) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003552 // Perform an initialization check for let declared variables.
3553 const Operator* op =
3554 javascript()->LoadContext(depth, variable->index(), false);
3555 Node* current = NewNode(op, current_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003556 value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3557 } else if (mode == CONST && op == Token::INIT) {
3558 // Perform an initialization check for const {this} variables.
3559 // Note that the {this} variable is the only const variable being able
3560 // to trigger bind operations outside the TDZ, via {super} calls.
3561 if (variable->is_this()) {
3562 const Operator* op =
3563 javascript()->LoadContext(depth, variable->index(), false);
3564 Node* current = NewNode(op, current_context());
3565 value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3566 }
3567 } else if (mode == CONST && op != Token::INIT) {
3568 // Assignment to const is exception in all modes.
3569 const Operator* op =
3570 javascript()->LoadContext(depth, variable->index(), false);
3571 Node* current = NewNode(op, current_context());
3572 BuildHoleCheckThenThrow(current, variable, value, bailout_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003573 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003574 }
3575 const Operator* op = javascript()->StoreContext(depth, variable->index());
3576 return NewNode(op, current_context(), value);
3577 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003578 case VariableLocation::LOOKUP: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003579 // Dynamic lookup of context variable (anywhere in the chain).
Ben Murdoch097c5b22016-05-18 11:27:45 +01003580 Handle<Name> name = variable->name();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003581 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
3582 // initializations of const declarations.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003583 Node* store = BuildDynamicStore(name, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003584 PrepareFrameState(store, bailout_id, combine);
3585 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003586 }
3587 }
3588 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003589 return nullptr;
3590}
3591
3592
3593Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3594 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003595 const Operator* op = javascript()->LoadProperty(feedback);
3596 Node* node = NewNode(op, object, key, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003597 return node;
3598}
3599
3600
3601Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3602 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003603 const Operator* op = javascript()->LoadNamed(name, feedback);
3604 Node* node = NewNode(op, object, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003605 return node;
3606}
3607
3608
3609Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3610 const VectorSlotPair& feedback) {
3611 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003612 Node* node = NewNode(op, object, key, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003613 return node;
3614}
3615
3616
3617Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3618 Node* value,
3619 const VectorSlotPair& feedback) {
3620 const Operator* op =
3621 javascript()->StoreNamed(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003622 Node* node = NewNode(op, object, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003623 return node;
3624}
3625
3626
3627Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3628 Handle<Name> name,
3629 const VectorSlotPair& feedback) {
3630 Node* name_node = jsgraph()->Constant(name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003631 const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
3632 Node* node = NewNode(op, receiver, home_object, name_node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003633 return node;
3634}
3635
3636
3637Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3638 Node* key,
3639 const VectorSlotPair& feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003640 const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
3641 Node* node = NewNode(op, receiver, home_object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003642 return node;
3643}
3644
3645
3646Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3647 Node* key, Node* value) {
3648 Runtime::FunctionId function_id = is_strict(language_mode())
3649 ? Runtime::kStoreKeyedToSuper_Strict
3650 : Runtime::kStoreKeyedToSuper_Sloppy;
3651 const Operator* op = javascript()->CallRuntime(function_id, 4);
3652 Node* node = NewNode(op, receiver, home_object, key, value);
3653 return node;
3654}
3655
3656
3657Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3658 Handle<Name> name, Node* value) {
3659 Node* name_node = jsgraph()->Constant(name);
3660 Runtime::FunctionId function_id = is_strict(language_mode())
3661 ? Runtime::kStoreToSuper_Strict
3662 : Runtime::kStoreToSuper_Sloppy;
3663 const Operator* op = javascript()->CallRuntime(function_id, 4);
3664 Node* node = NewNode(op, receiver, home_object, name_node, value);
3665 return node;
3666}
3667
3668
3669Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3670 const VectorSlotPair& feedback,
3671 TypeofMode typeof_mode) {
3672 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003673 Node* node = NewNode(op, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003674 return node;
3675}
3676
3677
3678Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3679 const VectorSlotPair& feedback) {
3680 const Operator* op =
3681 javascript()->StoreGlobal(language_mode(), name, feedback);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003682 Node* node = NewNode(op, value, GetFunctionClosure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003683 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003684}
3685
3686
Ben Murdoch097c5b22016-05-18 11:27:45 +01003687Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
3688 TypeofMode typeof_mode) {
3689 Node* name_node = jsgraph()->Constant(name);
3690 const Operator* op =
3691 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
3692 ? Runtime::kLoadLookupSlot
3693 : Runtime::kLoadLookupSlotInsideTypeof);
3694 Node* node = NewNode(op, name_node);
3695 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003696}
3697
3698
Ben Murdoch097c5b22016-05-18 11:27:45 +01003699Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
3700 Node* name_node = jsgraph()->Constant(name);
3701 const Operator* op = javascript()->CallRuntime(
3702 is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
3703 : Runtime::kStoreLookupSlot_Sloppy);
3704 Node* node = NewNode(op, name_node, value);
3705 return node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003706}
3707
3708
3709Node* AstGraphBuilder::BuildLoadGlobalObject() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003710 return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003711}
3712
3713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003714Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3715 const Operator* op =
3716 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3717 Node* native_context = NewNode(op, current_context());
3718 return NewNode(javascript()->LoadContext(0, index, true), native_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003719}
3720
3721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003722Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3723 if (Node* node = TryFastToBoolean(input)) return node;
3724 ToBooleanHints hints;
3725 if (!type_hint_analysis_ ||
3726 !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3727 hints = ToBooleanHint::kAny;
3728 }
3729 return NewNode(javascript()->ToBoolean(hints), input);
3730}
3731
3732
3733Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3734 if (Node* node = TryFastToName(input)) return node;
3735 Node* name = NewNode(javascript()->ToName(), input);
3736 PrepareFrameState(name, bailout_id);
3737 return name;
3738}
3739
3740
3741Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3742 Node* object = NewNode(javascript()->ToObject(), input);
3743 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3744 return object;
3745}
3746
3747
3748Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3749 ObjectLiteralProperty* property,
3750 int slot_number) {
3751 Expression* expr = property->value();
3752 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3753 Handle<Name> name = isolate()->factory()->home_object_symbol();
3754 FrameStateBeforeAndAfter states(this, BailoutId::None());
3755 VectorSlotPair feedback =
3756 CreateVectorSlotPair(property->GetSlot(slot_number));
3757 Node* store = BuildNamedStore(value, name, home_object, feedback);
3758 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3759 return store;
3760}
3761
3762
3763Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003764 const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003765 Node* call = NewNode(op, exception);
3766 PrepareFrameState(call, bailout_id);
3767 Node* control = NewNode(common()->Throw(), call);
3768 UpdateControlDependencyToLeaveFunction(control);
3769 return call;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003770}
3771
3772
3773Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3774 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003775 Node* variable_name = jsgraph()->Constant(variable->name());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003776 const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003777 Node* call = NewNode(op, variable_name);
3778 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003779 Node* control = NewNode(common()->Throw(), call);
3780 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003781 return call;
3782}
3783
3784
3785Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003786 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003787 javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003788 Node* call = NewNode(op);
3789 PrepareFrameState(call, bailout_id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003790 Node* control = NewNode(common()->Throw(), call);
3791 UpdateControlDependencyToLeaveFunction(control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003792 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003793}
3794
3795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003796Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3797 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003798 javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003799 Node* call = NewNode(op);
3800 PrepareFrameState(call, bailout_id);
3801 Node* control = NewNode(common()->Throw(), call);
3802 UpdateControlDependencyToLeaveFunction(control);
3803 return call;
3804}
3805
3806
3807Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3808 const Operator* op =
Ben Murdoch097c5b22016-05-18 11:27:45 +01003809 javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003810 Node* call = NewNode(op);
3811 PrepareFrameState(call, bailout_id);
3812 Node* control = NewNode(common()->Throw(), call);
3813 UpdateControlDependencyToLeaveFunction(control);
3814 return call;
3815}
3816
3817
3818Node* AstGraphBuilder::BuildReturn(Node* return_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003819 // Emit tracing call if requested to do so.
3820 if (FLAG_trace) {
3821 return_value =
3822 NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
3823 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003824 Node* control = NewNode(common()->Return(), return_value);
3825 UpdateControlDependencyToLeaveFunction(control);
3826 return control;
3827}
3828
3829
3830Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003831 NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003832 Node* control = NewNode(common()->Throw(), exception_value);
3833 UpdateControlDependencyToLeaveFunction(control);
3834 return control;
3835}
3836
3837
3838Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3839 TypeFeedbackId feedback_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003840 const Operator* js_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 BinaryOperationHints hints;
3842 if (!type_hint_analysis_ ||
3843 !type_hint_analysis_->GetBinaryOperationHints(feedback_id, &hints)) {
3844 hints = BinaryOperationHints::Any();
3845 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003846 switch (op) {
3847 case Token::BIT_OR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003848 js_op = javascript()->BitwiseOr(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003849 break;
3850 case Token::BIT_AND:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003851 js_op = javascript()->BitwiseAnd(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003852 break;
3853 case Token::BIT_XOR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003854 js_op = javascript()->BitwiseXor(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003855 break;
3856 case Token::SHL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003857 js_op = javascript()->ShiftLeft(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003858 break;
3859 case Token::SAR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003860 js_op = javascript()->ShiftRight(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003861 break;
3862 case Token::SHR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003863 js_op = javascript()->ShiftRightLogical(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003864 break;
3865 case Token::ADD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003866 js_op = javascript()->Add(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003867 break;
3868 case Token::SUB:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003869 js_op = javascript()->Subtract(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003870 break;
3871 case Token::MUL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003872 js_op = javascript()->Multiply(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003873 break;
3874 case Token::DIV:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003875 js_op = javascript()->Divide(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003876 break;
3877 case Token::MOD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01003878 js_op = javascript()->Modulus(hints);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003879 break;
3880 default:
3881 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003882 js_op = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003883 }
3884 return NewNode(js_op, left, right);
3885}
3886
3887
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003888Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3889 // Optimize global constants like "undefined", "Infinity", and "NaN".
3890 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3891 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3892 return nullptr;
3893}
3894
3895
3896Node* AstGraphBuilder::TryLoadDynamicVariable(
3897 Variable* variable, Handle<String> name, BailoutId bailout_id,
3898 FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
3899 OutputFrameStateCombine combine, TypeofMode typeof_mode) {
3900 VariableMode mode = variable->mode();
3901
3902 if (mode == DYNAMIC_GLOBAL) {
3903 uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3904 if (bitset == kFullCheckRequired) return nullptr;
3905
3906 // We are using two blocks to model fast and slow cases.
3907 BlockBuilder fast_block(this);
3908 BlockBuilder slow_block(this);
3909 environment()->Push(jsgraph()->TheHoleConstant());
3910 slow_block.BeginBlock();
3911 environment()->Pop();
3912 fast_block.BeginBlock();
3913
3914 // Perform checks whether the fast mode applies, by looking for any
3915 // extension object which might shadow the optimistic declaration.
3916 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3917 if ((bitset & 1) == 0) continue;
3918 Node* load = NewNode(
3919 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3920 current_context());
3921 Node* check = NewNode(javascript()->StrictEqual(), load,
3922 jsgraph()->TheHoleConstant());
3923 fast_block.BreakUnless(check, BranchHint::kTrue);
3924 }
3925
Ben Murdoch097c5b22016-05-18 11:27:45 +01003926 // Fast case, because variable is not shadowed.
3927 if (Node* constant = TryLoadGlobalConstant(name)) {
3928 environment()->Push(constant);
3929 } else {
3930 // Perform global slot load.
3931 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3932 states.AddToNode(fast, bailout_id, combine);
3933 environment()->Push(fast);
3934 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003935 slow_block.Break();
3936 environment()->Pop();
3937 fast_block.EndBlock();
3938
3939 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003940 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003941 states.AddToNode(slow, bailout_id, combine);
3942 environment()->Push(slow);
3943 slow_block.EndBlock();
3944
3945 return environment()->Pop();
3946 }
3947
3948 if (mode == DYNAMIC_LOCAL) {
3949 uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3950 if (bitset == kFullCheckRequired) return nullptr;
3951
3952 // We are using two blocks to model fast and slow cases.
3953 BlockBuilder fast_block(this);
3954 BlockBuilder slow_block(this);
3955 environment()->Push(jsgraph()->TheHoleConstant());
3956 slow_block.BeginBlock();
3957 environment()->Pop();
3958 fast_block.BeginBlock();
3959
3960 // Perform checks whether the fast mode applies, by looking for any
3961 // extension object which might shadow the optimistic declaration.
3962 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3963 if ((bitset & 1) == 0) continue;
3964 Node* load = NewNode(
3965 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3966 current_context());
3967 Node* check = NewNode(javascript()->StrictEqual(), load,
3968 jsgraph()->TheHoleConstant());
3969 fast_block.BreakUnless(check, BranchHint::kTrue);
3970 }
3971
3972 // Fast case, because variable is not shadowed. Perform context slot load.
3973 Variable* local = variable->local_if_not_shadowed();
3974 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3975 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3976 typeof_mode);
3977 environment()->Push(fast);
3978 slow_block.Break();
3979 environment()->Pop();
3980 fast_block.EndBlock();
3981
3982 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003983 Node* slow = BuildDynamicLoad(name, typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003984 states.AddToNode(slow, bailout_id, combine);
3985 environment()->Push(slow);
3986 slow_block.EndBlock();
3987
3988 return environment()->Pop();
3989 }
3990
3991 return nullptr;
3992}
3993
3994
3995Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3996 switch (input->opcode()) {
3997 case IrOpcode::kNumberConstant: {
3998 NumberMatcher m(input);
3999 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
4000 }
4001 case IrOpcode::kHeapConstant: {
4002 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4003 return jsgraph_->BooleanConstant(object->BooleanValue());
4004 }
4005 case IrOpcode::kJSEqual:
4006 case IrOpcode::kJSNotEqual:
4007 case IrOpcode::kJSStrictEqual:
4008 case IrOpcode::kJSStrictNotEqual:
4009 case IrOpcode::kJSLessThan:
4010 case IrOpcode::kJSLessThanOrEqual:
4011 case IrOpcode::kJSGreaterThan:
4012 case IrOpcode::kJSGreaterThanOrEqual:
4013 case IrOpcode::kJSToBoolean:
4014 case IrOpcode::kJSDeleteProperty:
4015 case IrOpcode::kJSHasProperty:
4016 case IrOpcode::kJSInstanceOf:
4017 return input;
4018 default:
4019 break;
4020 }
4021 return nullptr;
4022}
4023
4024
4025Node* AstGraphBuilder::TryFastToName(Node* input) {
4026 switch (input->opcode()) {
4027 case IrOpcode::kHeapConstant: {
4028 Handle<HeapObject> object = HeapObjectMatcher(input).Value();
4029 if (object->IsName()) return input;
4030 break;
4031 }
4032 case IrOpcode::kJSToString:
4033 case IrOpcode::kJSToName:
4034 case IrOpcode::kJSTypeOf:
4035 return input;
4036 default:
4037 break;
4038 }
4039 return nullptr;
4040}
4041
4042
4043bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4044 if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4045 info()->set_osr_expr_stack_height(std::max(
4046 environment()->stack_height(), info()->osr_expr_stack_height()));
4047 return true;
4048 }
4049 return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004050}
4051
4052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004053void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4054 OutputFrameStateCombine combine) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004055 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4056 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4057
4058 DCHECK_EQ(IrOpcode::kDead,
4059 NodeProperties::GetFrameStateInput(node, 0)->opcode());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004060 bool node_has_exception = NodeProperties::IsExceptionalCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004061 NodeProperties::ReplaceFrameStateInput(
Ben Murdoch097c5b22016-05-18 11:27:45 +01004062 node, 0,
4063 environment()->Checkpoint(ast_id, combine, node_has_exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004064 }
4065}
4066
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004067
4068BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4069 IterationStatement* stmt) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004070 if (loop_assignment_analysis_ == nullptr) return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004071 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004072}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004074
4075Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4076 if (size > input_buffer_size_) {
4077 size = size + kInputBufferSizeIncrement + input_buffer_size_;
4078 input_buffer_ = local_zone()->NewArray<Node*>(size);
4079 input_buffer_size_ = size;
4080 }
4081 return input_buffer_;
4082}
4083
4084
4085Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4086 Node** value_inputs, bool incomplete) {
4087 DCHECK_EQ(op->ValueInputCount(), value_input_count);
4088
4089 bool has_context = OperatorProperties::HasContextInput(op);
4090 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4091 bool has_control = op->ControlInputCount() == 1;
4092 bool has_effect = op->EffectInputCount() == 1;
4093
4094 DCHECK(op->ControlInputCount() < 2);
4095 DCHECK(op->EffectInputCount() < 2);
4096
4097 Node* result = nullptr;
4098 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4099 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4100 } else {
4101 bool inside_try_scope = try_nesting_level_ > 0;
4102 int input_count_with_deps = value_input_count;
4103 if (has_context) ++input_count_with_deps;
4104 input_count_with_deps += frame_state_count;
4105 if (has_control) ++input_count_with_deps;
4106 if (has_effect) ++input_count_with_deps;
4107 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4108 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4109 Node** current_input = buffer + value_input_count;
4110 if (has_context) {
4111 *current_input++ = current_context();
4112 }
4113 for (int i = 0; i < frame_state_count; i++) {
4114 // The frame state will be inserted later. Here we misuse
4115 // the {Dead} node as a sentinel to be later overwritten
4116 // with the real frame state.
4117 *current_input++ = jsgraph()->Dead();
4118 }
4119 if (has_effect) {
4120 *current_input++ = environment_->GetEffectDependency();
4121 }
4122 if (has_control) {
4123 *current_input++ = environment_->GetControlDependency();
4124 }
4125 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4126 if (!environment()->IsMarkedAsUnreachable()) {
4127 // Update the current control dependency for control-producing nodes.
4128 if (NodeProperties::IsControl(result)) {
4129 environment_->UpdateControlDependency(result);
4130 }
4131 // Update the current effect dependency for effect-producing nodes.
4132 if (result->op()->EffectOutputCount() > 0) {
4133 environment_->UpdateEffectDependency(result);
4134 }
4135 // Add implicit exception continuation for throwing nodes.
4136 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4137 // Conservative prediction whether caught locally.
4138 IfExceptionHint hint = try_catch_nesting_level_ > 0
4139 ? IfExceptionHint::kLocallyCaught
4140 : IfExceptionHint::kLocallyUncaught;
4141 // Copy the environment for the success continuation.
4142 Environment* success_env = environment()->CopyForConditional();
4143 const Operator* op = common()->IfException(hint);
4144 Node* effect = environment()->GetEffectDependency();
4145 Node* on_exception = graph()->NewNode(op, effect, result);
4146 environment_->UpdateControlDependency(on_exception);
4147 environment_->UpdateEffectDependency(on_exception);
4148 execution_control()->ThrowValue(on_exception);
4149 set_environment(success_env);
4150 }
4151 // Add implicit success continuation for throwing nodes.
4152 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4153 const Operator* op = common()->IfSuccess();
4154 Node* on_success = graph()->NewNode(op, result);
4155 environment_->UpdateControlDependency(on_success);
4156 }
4157 }
4158 }
4159
4160 return result;
4161}
4162
4163
4164void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4165 if (environment()->IsMarkedAsUnreachable()) return;
4166 environment()->MarkAsUnreachable();
4167 exit_controls_.push_back(exit);
4168}
4169
4170
4171void AstGraphBuilder::Environment::Merge(Environment* other) {
4172 DCHECK(values_.size() == other->values_.size());
4173 DCHECK(contexts_.size() == other->contexts_.size());
4174
4175 // Nothing to do if the other environment is dead.
4176 if (other->IsMarkedAsUnreachable()) return;
4177
4178 // Resurrect a dead environment by copying the contents of the other one and
4179 // placing a singleton merge as the new control dependency.
4180 if (this->IsMarkedAsUnreachable()) {
4181 Node* other_control = other->control_dependency_;
4182 Node* inputs[] = {other_control};
4183 control_dependency_ =
4184 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4185 effect_dependency_ = other->effect_dependency_;
4186 values_ = other->values_;
4187 contexts_ = other->contexts_;
4188 if (IsLivenessAnalysisEnabled()) {
4189 liveness_block_ =
4190 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4191 }
4192 return;
4193 }
4194
4195 // Record the merge for the local variable liveness calculation.
4196 // For loops, we are connecting a back edge into the existing block;
4197 // for merges, we create a new merged block.
4198 if (IsLivenessAnalysisEnabled()) {
4199 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4200 liveness_block_ =
4201 builder_->liveness_analyzer()->NewBlock(liveness_block());
4202 }
4203 liveness_block()->AddPredecessor(other->liveness_block());
4204 }
4205
4206 // Create a merge of the control dependencies of both environments and update
4207 // the current environment's control dependency accordingly.
4208 Node* control = builder_->MergeControl(this->GetControlDependency(),
4209 other->GetControlDependency());
4210 UpdateControlDependency(control);
4211
4212 // Create a merge of the effect dependencies of both environments and update
4213 // the current environment's effect dependency accordingly.
4214 Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4215 other->GetEffectDependency(), control);
4216 UpdateEffectDependency(effect);
4217
4218 // Introduce Phi nodes for values that have differing input at merge points,
4219 // potentially extending an existing Phi node if possible.
4220 for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4221 values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4222 }
4223 for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4224 contexts_[i] =
4225 builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4226 }
4227}
4228
4229
4230void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4231 bool is_osr) {
4232 int size = static_cast<int>(values()->size());
4233
4234 Node* control = builder_->NewLoop();
4235 if (assigned == nullptr) {
4236 // Assume that everything is updated in the loop.
4237 for (int i = 0; i < size; ++i) {
4238 values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4239 }
4240 } else {
4241 // Only build phis for those locals assigned in this loop.
4242 for (int i = 0; i < size; ++i) {
4243 if (i < assigned->length() && !assigned->Contains(i)) continue;
4244 Node* phi = builder_->NewPhi(1, values()->at(i), control);
4245 values()->at(i) = phi;
4246 }
4247 }
4248 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4249 UpdateEffectDependency(effect);
4250
4251 // Connect the loop to end via Terminate if it's not marked as unreachable.
4252 if (!IsMarkedAsUnreachable()) {
4253 // Connect the Loop node to end via a Terminate node.
4254 Node* terminate = builder_->graph()->NewNode(
4255 builder_->common()->Terminate(), effect, control);
4256 builder_->exit_controls_.push_back(terminate);
4257 }
4258
4259 if (builder_->info()->is_osr()) {
4260 // Introduce phis for all context values in the case of an OSR graph.
4261 for (size_t i = 0; i < contexts()->size(); ++i) {
4262 Node* context = contexts()->at(i);
4263 contexts()->at(i) = builder_->NewPhi(1, context, control);
4264 }
4265 }
4266
4267 if (is_osr) {
4268 // Merge OSR values as inputs to the phis of the loop.
4269 Graph* graph = builder_->graph();
4270 Node* osr_loop_entry = builder_->graph()->NewNode(
4271 builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4272
4273 builder_->MergeControl(control, osr_loop_entry);
4274 builder_->MergeEffect(effect, osr_loop_entry, control);
4275
4276 for (int i = 0; i < size; ++i) {
4277 Node* value = values()->at(i);
4278 Node* osr_value =
4279 graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4280 values()->at(i) = builder_->MergeValue(value, osr_value, control);
4281 }
4282
4283 // Rename all the contexts in the environment.
4284 // The innermost context is the OSR value, and the outer contexts are
4285 // reconstructed by dynamically walking up the context chain.
4286 Node* osr_context = nullptr;
4287 const Operator* op =
4288 builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4289 const Operator* op_inner =
4290 builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4291 int last = static_cast<int>(contexts()->size() - 1);
4292 for (int i = last; i >= 0; i--) {
4293 Node* context = contexts()->at(i);
4294 osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4295 : graph->NewNode(op, osr_context, osr_context,
4296 osr_loop_entry);
4297 contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4298 }
4299 }
4300}
4301
4302
4303Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4304 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4305 Node** buffer = EnsureInputBufferSize(count + 1);
4306 MemsetPointer(buffer, input, count);
4307 buffer[count] = control;
4308 return graph()->NewNode(phi_op, count + 1, buffer, true);
4309}
4310
4311
4312// TODO(mstarzinger): Revisit this once we have proper effect states.
4313Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4314 const Operator* phi_op = common()->EffectPhi(count);
4315 Node** buffer = EnsureInputBufferSize(count + 1);
4316 MemsetPointer(buffer, input, count);
4317 buffer[count] = control;
4318 return graph()->NewNode(phi_op, count + 1, buffer, true);
4319}
4320
4321
4322Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4323 int inputs = control->op()->ControlInputCount() + 1;
4324 if (control->opcode() == IrOpcode::kLoop) {
4325 // Control node for loop exists, add input.
4326 const Operator* op = common()->Loop(inputs);
4327 control->AppendInput(graph_zone(), other);
4328 NodeProperties::ChangeOp(control, op);
4329 } else if (control->opcode() == IrOpcode::kMerge) {
4330 // Control node for merge exists, add input.
4331 const Operator* op = common()->Merge(inputs);
4332 control->AppendInput(graph_zone(), other);
4333 NodeProperties::ChangeOp(control, op);
4334 } else {
4335 // Control node is a singleton, introduce a merge.
4336 const Operator* op = common()->Merge(inputs);
4337 Node* inputs[] = {control, other};
4338 control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4339 }
4340 return control;
4341}
4342
4343
4344Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4345 int inputs = control->op()->ControlInputCount();
4346 if (value->opcode() == IrOpcode::kEffectPhi &&
4347 NodeProperties::GetControlInput(value) == control) {
4348 // Phi already exists, add input.
4349 value->InsertInput(graph_zone(), inputs - 1, other);
4350 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4351 } else if (value != other) {
4352 // Phi does not exist yet, introduce one.
4353 value = NewEffectPhi(inputs, value, control);
4354 value->ReplaceInput(inputs - 1, other);
4355 }
4356 return value;
4357}
4358
4359
4360Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4361 int inputs = control->op()->ControlInputCount();
4362 if (value->opcode() == IrOpcode::kPhi &&
4363 NodeProperties::GetControlInput(value) == control) {
4364 // Phi already exists, add input.
4365 value->InsertInput(graph_zone(), inputs - 1, other);
4366 NodeProperties::ChangeOp(
4367 value, common()->Phi(MachineRepresentation::kTagged, inputs));
4368 } else if (value != other) {
4369 // Phi does not exist yet, introduce one.
4370 value = NewPhi(inputs, value, control);
4371 value->ReplaceInput(inputs - 1, other);
4372 }
4373 return value;
4374}
4375
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004376} // namespace compiler
4377} // namespace internal
4378} // namespace v8