blob: cde5e7182df0cba24ed1147a4b503d62a9b0a9e9 [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
7#include "src/compiler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include "src/compiler/ast-loop-assignment-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/control-builders.h"
10#include "src/compiler/machine-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/compiler/node-matchers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/compiler/node-properties-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/compiler/node-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/full-codegen.h"
15#include "src/parser.h"
16#include "src/scopes.h"
17
18namespace v8 {
19namespace internal {
20namespace compiler {
21
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
23 JSGraph* jsgraph, LoopAssignmentAnalysis* loop)
24 : StructuredGraphBuilder(local_zone, jsgraph->graph(), jsgraph->common()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025 info_(info),
26 jsgraph_(jsgraph),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040027 globals_(0, local_zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 breakable_(NULL),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029 execution_context_(NULL),
30 loop_assignment_analysis_(loop) {
31 InitializeAstVisitor(local_zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032}
33
34
35Node* AstGraphBuilder::GetFunctionClosure() {
36 if (!function_closure_.is_set()) {
37 // Parameter -1 is special for the function closure
38 const Operator* op = common()->Parameter(-1);
39 Node* node = NewNode(op, graph()->start());
40 function_closure_.set(node);
41 }
42 return function_closure_.get();
43}
44
45
46Node* AstGraphBuilder::GetFunctionContext() {
47 if (!function_context_.is_set()) {
48 // Parameter (arity + 1) is special for the outer context of the function
49 const Operator* op = common()->Parameter(info()->num_parameters() + 1);
50 Node* node = NewNode(op, graph()->start());
51 function_context_.set(node);
52 }
53 return function_context_.get();
54}
55
56
57bool AstGraphBuilder::CreateGraph() {
58 Scope* scope = info()->scope();
59 DCHECK(graph() != NULL);
60
61 // Set up the basic structure of the graph.
62 int parameter_count = info()->num_parameters();
63 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));
64
65 // Initialize the top-level environment.
66 Environment env(this, scope, graph()->start());
67 set_environment(&env);
68
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069 // Initialize the incoming context.
70 Node* outer_context = GetFunctionContext();
71 set_current_context(outer_context);
72
73 // Build receiver check for sloppy mode if necessary.
74 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
75 Node* original_receiver = env.Lookup(scope->receiver());
76 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
77 env.Bind(scope->receiver(), patched_receiver);
78
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 // Build node to initialize local function context.
80 Node* closure = GetFunctionClosure();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040081 Node* inner_context = BuildLocalFunctionContext(outer_context, closure);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082
83 // Push top-level function scope for the function body.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 ContextScope top_context(this, scope, inner_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085
86 // Build the arguments object if it is used.
87 BuildArgumentsObject(scope->arguments());
88
89 // Emit tracing call if requested to do so.
90 if (FLAG_trace) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 }
93
94 // Visit implicit declaration of the function name.
95 if (scope->is_function_scope() && scope->function() != NULL) {
96 VisitVariableDeclaration(scope->function());
97 }
98
99 // Visit declarations within the function scope.
100 VisitDeclarations(scope->declarations());
101
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102 // Build a stack-check before the body.
103 Node* node = BuildStackCheck();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 PrepareFrameState(node, BailoutId::FunctionEntry());
105
106 // Visit statements in the function body.
107 VisitStatements(info()->function()->body());
108 if (HasStackOverflow()) return false;
109
110 // Emit tracing call if requested to do so.
111 if (FLAG_trace) {
112 // TODO(mstarzinger): Only traces implicit return.
113 Node* return_value = jsgraph()->UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400114 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 }
116
117 // Return 'undefined' in case we can fall off the end.
118 Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant());
119 UpdateControlDependencyToLeaveFunction(control);
120
121 // Finish the basic structure of the graph.
122 environment()->UpdateControlDependency(exit_control());
123 graph()->SetEnd(NewNode(common()->End()));
124
125 return true;
126}
127
128
129// Left-hand side can only be a property, a global or a variable slot.
130enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
131
132
133// Determine the left-hand side kind of an assignment.
134static LhsKind DetermineLhsKind(Expression* expr) {
135 Property* property = expr->AsProperty();
136 DCHECK(expr->IsValidReferenceExpression());
137 LhsKind lhs_kind =
138 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName())
139 ? NAMED_PROPERTY
140 : KEYED_PROPERTY;
141 return lhs_kind;
142}
143
144
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment(
146 StructuredGraphBuilder::Environment* env) {
147 return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
148}
149
150
151AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
152 Scope* scope,
153 Node* control_dependency)
154 : StructuredGraphBuilder::Environment(builder, control_dependency),
155 parameters_count_(scope->num_parameters() + 1),
156 locals_count_(scope->num_stack_slots()),
157 parameters_node_(NULL),
158 locals_node_(NULL),
159 stack_node_(NULL) {
160 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
161
162 // Bind the receiver variable.
163 Node* receiver = builder->graph()->NewNode(common()->Parameter(0),
164 builder->graph()->start());
165 values()->push_back(receiver);
166
167 // Bind all parameter variables. The parameter indices are shifted by 1
168 // (receiver is parameter index -1 but environment index 0).
169 for (int i = 0; i < scope->num_parameters(); ++i) {
170 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1),
171 builder->graph()->start());
172 values()->push_back(parameter);
173 }
174
175 // Bind all local variables to undefined.
176 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
177 values()->insert(values()->end(), locals_count(), undefined_constant);
178}
179
180
181AstGraphBuilder::Environment::Environment(const Environment& copy)
182 : StructuredGraphBuilder::Environment(
183 static_cast<StructuredGraphBuilder::Environment>(copy)),
184 parameters_count_(copy.parameters_count_),
185 locals_count_(copy.locals_count_),
186 parameters_node_(copy.parameters_node_),
187 locals_node_(copy.locals_node_),
188 stack_node_(copy.stack_node_) {}
189
190
191void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
192 int offset, int count) {
193 bool should_update = false;
194 Node** env_values = (count == 0) ? NULL : &values()->at(offset);
195 if (*state_values == NULL || (*state_values)->InputCount() != count) {
196 should_update = true;
197 } else {
198 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
199 for (int i = 0; i < count; i++) {
200 if ((*state_values)->InputAt(i) != env_values[i]) {
201 should_update = true;
202 break;
203 }
204 }
205 }
206 if (should_update) {
207 const Operator* op = common()->StateValues(count);
208 (*state_values) = graph()->NewNode(op, count, env_values);
209 }
210}
211
212
213Node* AstGraphBuilder::Environment::Checkpoint(
214 BailoutId ast_id, OutputFrameStateCombine combine) {
215 UpdateStateValues(&parameters_node_, 0, parameters_count());
216 UpdateStateValues(&locals_node_, parameters_count(), locals_count());
217 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
218 stack_height());
219
220 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine);
221
222 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_,
223 GetContext(),
224 builder()->jsgraph()->UndefinedConstant());
225}
226
227
228AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
229 Expression::Context kind)
230 : kind_(kind), owner_(own), outer_(own->ast_context()) {
231 owner()->set_ast_context(this); // Push.
232#ifdef DEBUG
233 original_height_ = environment()->stack_height();
234#endif
235}
236
237
238AstGraphBuilder::AstContext::~AstContext() {
239 owner()->set_ast_context(outer_); // Pop.
240}
241
242
243AstGraphBuilder::AstEffectContext::~AstEffectContext() {
244 DCHECK(environment()->stack_height() == original_height_);
245}
246
247
248AstGraphBuilder::AstValueContext::~AstValueContext() {
249 DCHECK(environment()->stack_height() == original_height_ + 1);
250}
251
252
253AstGraphBuilder::AstTestContext::~AstTestContext() {
254 DCHECK(environment()->stack_height() == original_height_ + 1);
255}
256
257
258void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
259 // The value is ignored.
260}
261
262
263void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
264 environment()->Push(value);
265}
266
267
268void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
269 environment()->Push(owner()->BuildToBoolean(value));
270}
271
272
273Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
274
275
276Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
277 return environment()->Pop();
278}
279
280
281Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
282 return environment()->Pop();
283}
284
285
286AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable(
287 BreakableStatement* target) {
288 BreakableScope* current = this;
289 while (current != NULL && current->target_ != target) {
290 owner_->environment()->Drop(current->drop_extra_);
291 current = current->next_;
292 }
293 DCHECK(current != NULL); // Always found (unless stack is malformed).
294 return current;
295}
296
297
298void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) {
299 FindBreakable(stmt)->control_->Break();
300}
301
302
303void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) {
304 FindBreakable(stmt)->control_->Continue();
305}
306
307
308void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
309 if (expr == NULL) {
310 return environment()->Push(jsgraph()->NullConstant());
311 }
312 VisitForValue(expr);
313}
314
315
316void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
317 for (int i = 0; i < exprs->length(); ++i) {
318 VisitForValue(exprs->at(i));
319 }
320}
321
322
323void AstGraphBuilder::VisitForValue(Expression* expr) {
324 AstValueContext for_value(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400327 } else {
328 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 }
330}
331
332
333void AstGraphBuilder::VisitForEffect(Expression* expr) {
334 AstEffectContext for_effect(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 } else {
338 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 }
340}
341
342
343void AstGraphBuilder::VisitForTest(Expression* expr) {
344 AstTestContext for_condition(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345 if (!CheckStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 expr->Accept(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347 } else {
348 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
349 }
350}
351
352
353void AstGraphBuilder::Visit(Expression* expr) {
354 // Reuses enclosing AstContext.
355 if (!CheckStackOverflow()) {
356 expr->Accept(this);
357 } else {
358 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 }
360}
361
362
363void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
364 Variable* variable = decl->proxy()->var();
365 VariableMode mode = decl->mode();
366 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
367 switch (variable->location()) {
368 case Variable::UNALLOCATED: {
369 Handle<Oddball> value = variable->binding_needs_init()
370 ? isolate()->factory()->the_hole_value()
371 : isolate()->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372 globals()->push_back(variable->name());
373 globals()->push_back(value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 break;
375 }
376 case Variable::PARAMETER:
377 case Variable::LOCAL:
378 if (hole_init) {
379 Node* value = jsgraph()->TheHoleConstant();
380 environment()->Bind(variable, value);
381 }
382 break;
383 case Variable::CONTEXT:
384 if (hole_init) {
385 Node* value = jsgraph()->TheHoleConstant();
386 const Operator* op = javascript()->StoreContext(0, variable->index());
387 NewNode(op, current_context(), value);
388 }
389 break;
390 case Variable::LOOKUP:
391 UNIMPLEMENTED();
392 }
393}
394
395
396void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
397 Variable* variable = decl->proxy()->var();
398 switch (variable->location()) {
399 case Variable::UNALLOCATED: {
400 Handle<SharedFunctionInfo> function =
401 Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info());
402 // Check for stack-overflow exception.
403 if (function.is_null()) return SetStackOverflow();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400404 globals()->push_back(variable->name());
405 globals()->push_back(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 break;
407 }
408 case Variable::PARAMETER:
409 case Variable::LOCAL: {
410 VisitForValue(decl->fun());
411 Node* value = environment()->Pop();
412 environment()->Bind(variable, value);
413 break;
414 }
415 case Variable::CONTEXT: {
416 VisitForValue(decl->fun());
417 Node* value = environment()->Pop();
418 const Operator* op = javascript()->StoreContext(0, variable->index());
419 NewNode(op, current_context(), value);
420 break;
421 }
422 case Variable::LOOKUP:
423 UNIMPLEMENTED();
424 }
425}
426
427
428void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
429 UNREACHABLE();
430}
431
432
433void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
434 UNREACHABLE();
435}
436
437
438void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
439 UNREACHABLE();
440}
441
442
443void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }
444
445
446void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) {
447 UNREACHABLE();
448}
449
450
451void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
452
453
454void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
455
456
457void AstGraphBuilder::VisitBlock(Block* stmt) {
458 BlockBuilder block(this);
459 BreakableScope scope(this, stmt, &block, 0);
460 if (stmt->labels() != NULL) block.BeginBlock();
461 if (stmt->scope() == NULL) {
462 // Visit statements in the same scope, no declarations.
463 VisitStatements(stmt->statements());
464 } else {
465 const Operator* op = javascript()->CreateBlockContext();
466 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo());
467 Node* context = NewNode(op, scope_info, GetFunctionClosure());
468 ContextScope scope(this, stmt->scope(), context);
469
470 // Visit declarations and statements in a block scope.
471 VisitDeclarations(stmt->scope()->declarations());
472 VisitStatements(stmt->statements());
473 }
474 if (stmt->labels() != NULL) block.EndBlock();
475}
476
477
478void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
479 UNREACHABLE();
480}
481
482
483void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
484 VisitForEffect(stmt->expression());
485}
486
487
488void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
489 // Do nothing.
490}
491
492
493void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
494 IfBuilder compare_if(this);
495 VisitForTest(stmt->condition());
496 Node* condition = environment()->Pop();
497 compare_if.If(condition);
498 compare_if.Then();
499 Visit(stmt->then_statement());
500 compare_if.Else();
501 Visit(stmt->else_statement());
502 compare_if.End();
503}
504
505
506void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
507 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
508 breakable()->ContinueTarget(stmt->target());
509 set_environment(env);
510}
511
512
513void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
514 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
515 breakable()->BreakTarget(stmt->target());
516 set_environment(env);
517}
518
519
520void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
521 VisitForValue(stmt->expression());
522 Node* result = environment()->Pop();
523 Node* control = NewNode(common()->Return(), result);
524 UpdateControlDependencyToLeaveFunction(control);
525}
526
527
528void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
529 VisitForValue(stmt->expression());
530 Node* value = environment()->Pop();
531 const Operator* op = javascript()->CreateWithContext();
532 Node* context = NewNode(op, value, GetFunctionClosure());
533 ContextScope scope(this, stmt->scope(), context);
534 Visit(stmt->statement());
535}
536
537
538void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
539 ZoneList<CaseClause*>* clauses = stmt->cases();
540 SwitchBuilder compare_switch(this, clauses->length());
541 BreakableScope scope(this, stmt, &compare_switch, 0);
542 compare_switch.BeginSwitch();
543 int default_index = -1;
544
545 // Keep the switch value on the stack until a case matches.
546 VisitForValue(stmt->tag());
547 Node* tag = environment()->Top();
548
549 // Iterate over all cases and create nodes for label comparison.
550 for (int i = 0; i < clauses->length(); i++) {
551 CaseClause* clause = clauses->at(i);
552
553 // The default is not a test, remember index.
554 if (clause->is_default()) {
555 default_index = i;
556 continue;
557 }
558
559 // Create nodes to perform label comparison as if via '==='. The switch
560 // value is still on the operand stack while the label is evaluated.
561 VisitForValue(clause->label());
562 Node* label = environment()->Pop();
563 const Operator* op = javascript()->StrictEqual();
564 Node* condition = NewNode(op, tag, label);
565 compare_switch.BeginLabel(i, condition);
566
567 // Discard the switch value at label match.
568 environment()->Pop();
569 compare_switch.EndLabel();
570 }
571
572 // Discard the switch value and mark the default case.
573 environment()->Pop();
574 if (default_index >= 0) {
575 compare_switch.DefaultAt(default_index);
576 }
577
578 // Iterate over all cases and create nodes for case bodies.
579 for (int i = 0; i < clauses->length(); i++) {
580 CaseClause* clause = clauses->at(i);
581 compare_switch.BeginCase(i);
582 VisitStatements(clause->statements());
583 compare_switch.EndCase();
584 }
585
586 compare_switch.EndSwitch();
587}
588
589
590void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
591 LoopBuilder while_loop(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 VisitIterationBody(stmt, &while_loop, 0);
594 while_loop.EndBody();
595 VisitForTest(stmt->cond());
596 Node* condition = environment()->Pop();
597 while_loop.BreakUnless(condition);
598 while_loop.EndLoop();
599}
600
601
602void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
603 LoopBuilder while_loop(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 VisitForTest(stmt->cond());
606 Node* condition = environment()->Pop();
607 while_loop.BreakUnless(condition);
608 VisitIterationBody(stmt, &while_loop, 0);
609 while_loop.EndBody();
610 while_loop.EndLoop();
611}
612
613
614void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
615 LoopBuilder for_loop(this);
616 VisitIfNotNull(stmt->init());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 if (stmt->cond() != NULL) {
619 VisitForTest(stmt->cond());
620 Node* condition = environment()->Pop();
621 for_loop.BreakUnless(condition);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400622 } else {
623 for_loop.BreakUnless(jsgraph()->TrueConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 }
625 VisitIterationBody(stmt, &for_loop, 0);
626 for_loop.EndBody();
627 VisitIfNotNull(stmt->next());
628 for_loop.EndLoop();
629}
630
631
632// TODO(dcarney): this is a big function. Try to clean up some.
633void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
634 VisitForValue(stmt->subject());
635 Node* obj = environment()->Pop();
636 // Check for undefined or null before entering loop.
637 IfBuilder is_undefined(this);
638 Node* is_undefined_cond =
639 NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant());
640 is_undefined.If(is_undefined_cond);
641 is_undefined.Then();
642 is_undefined.Else();
643 {
644 IfBuilder is_null(this);
645 Node* is_null_cond =
646 NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
647 is_null.If(is_null_cond);
648 is_null.Then();
649 is_null.Else();
650 // Convert object to jsobject.
651 // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
652 obj = NewNode(javascript()->ToObject(), obj);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400653 PrepareFrameState(obj, stmt->ToObjectId(), OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 environment()->Push(obj);
655 // TODO(dcarney): should do a fast enum cache check here to skip runtime.
656 environment()->Push(obj);
657 Node* cache_type = ProcessArguments(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400658 javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), 1);
659 PrepareFrameState(cache_type, stmt->EnumId(),
660 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 // TODO(dcarney): these next runtime calls should be removed in favour of
662 // a few simplified instructions.
663 environment()->Push(obj);
664 environment()->Push(cache_type);
665 Node* cache_pair =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400666 ProcessArguments(javascript()->CallRuntime(Runtime::kForInInit, 2), 2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 // cache_type may have been replaced.
668 Node* cache_array = NewNode(common()->Projection(0), cache_pair);
669 cache_type = NewNode(common()->Projection(1), cache_pair);
670 environment()->Push(cache_type);
671 environment()->Push(cache_array);
672 Node* cache_length = ProcessArguments(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673 javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2), 2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 {
675 // TODO(dcarney): this check is actually supposed to be for the
676 // empty enum case only.
677 IfBuilder have_no_properties(this);
678 Node* empty_array_cond = NewNode(javascript()->StrictEqual(),
679 cache_length, jsgraph()->ZeroConstant());
680 have_no_properties.If(empty_array_cond);
681 have_no_properties.Then();
682 // Pop obj and skip loop.
683 environment()->Pop();
684 have_no_properties.Else();
685 {
686 // Construct the rest of the environment.
687 environment()->Push(cache_type);
688 environment()->Push(cache_array);
689 environment()->Push(cache_length);
690 environment()->Push(jsgraph()->ZeroConstant());
691 // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
692 LoopBuilder for_loop(this);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400693 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 // Check loop termination condition.
695 Node* index = environment()->Peek(0);
696 Node* exit_cond =
697 NewNode(javascript()->LessThan(), index, cache_length);
698 // TODO(jarin): provide real bailout id.
699 PrepareFrameState(exit_cond, BailoutId::None());
700 for_loop.BreakUnless(exit_cond);
701 // TODO(dcarney): this runtime call should be a handful of
702 // simplified instructions that
703 // basically produce
704 // value = array[index]
705 environment()->Push(obj);
706 environment()->Push(cache_array);
707 environment()->Push(cache_type);
708 environment()->Push(index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709 Node* pair = ProcessArguments(
710 javascript()->CallRuntime(Runtime::kForInNext, 4), 4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 Node* value = NewNode(common()->Projection(0), pair);
712 Node* should_filter = NewNode(common()->Projection(1), pair);
713 environment()->Push(value);
714 {
715 // Test if FILTER_KEY needs to be called.
716 IfBuilder test_should_filter(this);
717 Node* should_filter_cond =
718 NewNode(javascript()->StrictEqual(), should_filter,
719 jsgraph()->TrueConstant());
720 test_should_filter.If(should_filter_cond);
721 test_should_filter.Then();
722 value = environment()->Pop();
723 Node* builtins = BuildLoadBuiltinsObject();
724 Node* function = BuildLoadObjectField(
725 builtins,
726 JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
727 // Callee.
728 environment()->Push(function);
729 // Receiver.
730 environment()->Push(obj);
731 // Args.
732 environment()->Push(value);
733 // result is either the string key or Smi(0) indicating the property
734 // is gone.
735 Node* res = ProcessArguments(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400736 javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 // TODO(jarin): provide real bailout id.
738 PrepareFrameState(res, BailoutId::None());
739 Node* property_missing = NewNode(javascript()->StrictEqual(), res,
740 jsgraph()->ZeroConstant());
741 {
742 IfBuilder is_property_missing(this);
743 is_property_missing.If(property_missing);
744 is_property_missing.Then();
745 // Inc counter and continue.
746 Node* index_inc =
747 NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
748 // TODO(jarin): provide real bailout id.
749 PrepareFrameState(index_inc, BailoutId::None());
750 environment()->Poke(0, index_inc);
751 for_loop.Continue();
752 is_property_missing.Else();
753 is_property_missing.End();
754 }
755 // Replace 'value' in environment.
756 environment()->Push(res);
757 test_should_filter.Else();
758 test_should_filter.End();
759 }
760 value = environment()->Pop();
761 // Bind value and do loop body.
762 VisitForInAssignment(stmt->each(), value);
763 VisitIterationBody(stmt, &for_loop, 5);
764 for_loop.EndBody();
765 // Inc counter and continue.
766 Node* index_inc =
767 NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
768 // TODO(jarin): provide real bailout id.
769 PrepareFrameState(index_inc, BailoutId::None());
770 environment()->Poke(0, index_inc);
771 for_loop.EndLoop();
772 environment()->Drop(5);
773 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
774 }
775 have_no_properties.End();
776 }
777 is_null.End();
778 }
779 is_undefined.End();
780}
781
782
783void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
784 VisitForValue(stmt->subject());
785 environment()->Pop();
786 // TODO(turbofan): create and use loop builder.
787}
788
789
790void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
791 UNREACHABLE();
792}
793
794
795void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
796 UNREACHABLE();
797}
798
799
800void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
801 // TODO(turbofan): Do we really need a separate reloc-info for this?
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400802 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000803 PrepareFrameState(node, stmt->DebugBreakId());
804}
805
806
807void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
808 Node* context = current_context();
809
810 // Build a new shared function info if we cannot find one in the baseline
811 // code. We also have a stack overflow if the recursive compilation did.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400812 expr->InitializeSharedInfo(handle(info()->shared_info()->code()));
813 Handle<SharedFunctionInfo> shared_info = expr->shared_info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 if (shared_info.is_null()) {
815 shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info());
816 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow?
817 }
818
819 // Create node to instantiate a new closure.
820 Node* info = jsgraph()->Constant(shared_info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400821 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure());
822 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000823 Node* value = NewNode(op, context, info, pretenure);
824 ast_context()->ProduceValue(value);
825}
826
827
828void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 UNREACHABLE();
830}
831
832
833void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
834 UNREACHABLE();
835}
836
837
838void AstGraphBuilder::VisitConditional(Conditional* expr) {
839 IfBuilder compare_if(this);
840 VisitForTest(expr->condition());
841 Node* condition = environment()->Pop();
842 compare_if.If(condition);
843 compare_if.Then();
844 Visit(expr->then_expression());
845 compare_if.Else();
846 Visit(expr->else_expression());
847 compare_if.End();
848 ast_context()->ReplaceValue();
849}
850
851
852void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400853 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
854 Node* value = BuildVariableLoad(expr->var(), expr->id(), pair);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 ast_context()->ProduceValue(value);
856}
857
858
859void AstGraphBuilder::VisitLiteral(Literal* expr) {
860 Node* value = jsgraph()->Constant(expr->value());
861 ast_context()->ProduceValue(value);
862}
863
864
865void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
866 Node* closure = GetFunctionClosure();
867
868 // Create node to materialize a regular expression literal.
869 Node* literals_array =
870 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
871 Node* literal_index = jsgraph()->Constant(expr->literal_index());
872 Node* pattern = jsgraph()->Constant(expr->pattern());
873 Node* flags = jsgraph()->Constant(expr->flags());
874 const Operator* op =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 javascript()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400877 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 ast_context()->ProduceValue(literal);
879}
880
881
882void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
883 Node* closure = GetFunctionClosure();
884
885 // Create node to deep-copy the literal boilerplate.
886 expr->BuildConstantProperties(isolate());
887 Node* literals_array =
888 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
889 Node* literal_index = jsgraph()->Constant(expr->literal_index());
890 Node* constants = jsgraph()->Constant(expr->constant_properties());
891 Node* flags = jsgraph()->Constant(expr->ComputeFlags());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 const Operator* op =
893 javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400895 PrepareFrameState(literal, expr->CreateLiteralId(),
896 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897
898 // The object is expected on the operand stack during computation of the
899 // property values and is the value of the entire expression.
900 environment()->Push(literal);
901
902 // Mark all computed expressions that are bound to a key that is shadowed by
903 // a later occurrence of the same key. For the marked expressions, no store
904 // code is emitted.
905 expr->CalculateEmitStore(zone());
906
907 // Create nodes to store computed values into the literal.
908 AccessorTable accessor_table(zone());
909 for (int i = 0; i < expr->properties()->length(); i++) {
910 ObjectLiteral::Property* property = expr->properties()->at(i);
911 if (property->IsCompileTimeValue()) continue;
912
913 Literal* key = property->key();
914 switch (property->kind()) {
915 case ObjectLiteral::Property::CONSTANT:
916 UNREACHABLE();
917 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
918 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
919 // Fall through.
920 case ObjectLiteral::Property::COMPUTED: {
921 // It is safe to use [[Put]] here because the boilerplate already
922 // contains computed properties with an uninitialized value.
923 if (key->value()->IsInternalizedString()) {
924 if (property->emit_store()) {
925 VisitForValue(property->value());
926 Node* value = environment()->Pop();
927 Unique<Name> name = MakeUnique(key->AsPropertyName());
928 Node* store = NewNode(javascript()->StoreNamed(strict_mode(), name),
929 literal, value);
930 PrepareFrameState(store, key->id());
931 } else {
932 VisitForEffect(property->value());
933 }
934 break;
935 }
936 environment()->Push(literal); // Duplicate receiver.
937 VisitForValue(property->key());
938 VisitForValue(property->value());
939 Node* value = environment()->Pop();
940 Node* key = environment()->Pop();
941 Node* receiver = environment()->Pop();
942 if (property->emit_store()) {
943 Node* strict = jsgraph()->Constant(SLOPPY);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400944 const Operator* op =
945 javascript()->CallRuntime(Runtime::kSetProperty, 4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 NewNode(op, receiver, key, value, strict);
947 }
948 break;
949 }
950 case ObjectLiteral::Property::PROTOTYPE: {
951 environment()->Push(literal); // Duplicate receiver.
952 VisitForValue(property->value());
953 Node* value = environment()->Pop();
954 Node* receiver = environment()->Pop();
955 if (property->emit_store()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400956 const Operator* op =
957 javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
958 Node* set_prototype = NewNode(op, receiver, value);
959 // SetPrototype should not lazy deopt on an object
960 // literal.
961 PrepareFrameState(set_prototype, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 }
963 break;
964 }
965 case ObjectLiteral::Property::GETTER:
966 accessor_table.lookup(key)->second->getter = property->value();
967 break;
968 case ObjectLiteral::Property::SETTER:
969 accessor_table.lookup(key)->second->setter = property->value();
970 break;
971 }
972 }
973
974 // Create nodes to define accessors, using only a single call to the runtime
975 // for each pair of corresponding getters and setters.
976 for (AccessorTable::Iterator it = accessor_table.begin();
977 it != accessor_table.end(); ++it) {
978 VisitForValue(it->first);
979 VisitForValueOrNull(it->second->getter);
980 VisitForValueOrNull(it->second->setter);
981 Node* setter = environment()->Pop();
982 Node* getter = environment()->Pop();
983 Node* name = environment()->Pop();
984 Node* attr = jsgraph()->Constant(NONE);
985 const Operator* op =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 Node* call = NewNode(op, literal, name, getter, setter, attr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400988 // This should not lazy deopt on a new literal.
989 PrepareFrameState(call, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 }
991
992 // Transform literals that contain functions to fast properties.
993 if (expr->has_function()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400994 const Operator* op =
995 javascript()->CallRuntime(Runtime::kToFastProperties, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 NewNode(op, literal);
997 }
998
999 ast_context()->ProduceValue(environment()->Pop());
1000}
1001
1002
1003void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1004 Node* closure = GetFunctionClosure();
1005
1006 // Create node to deep-copy the literal boilerplate.
1007 expr->BuildConstantElements(isolate());
1008 Node* literals_array =
1009 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1010 Node* literal_index = jsgraph()->Constant(expr->literal_index());
1011 Node* constants = jsgraph()->Constant(expr->constant_elements());
1012 Node* flags = jsgraph()->Constant(expr->ComputeFlags());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001013 const Operator* op =
1014 javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
1016
1017 // The array and the literal index are both expected on the operand stack
1018 // during computation of the element values.
1019 environment()->Push(literal);
1020 environment()->Push(literal_index);
1021
1022 // Create nodes to evaluate all the non-constant subexpressions and to store
1023 // them into the newly cloned array.
1024 for (int i = 0; i < expr->values()->length(); i++) {
1025 Expression* subexpr = expr->values()->at(i);
1026 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1027
1028 VisitForValue(subexpr);
1029 Node* value = environment()->Pop();
1030 Node* index = jsgraph()->Constant(i);
1031 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), literal,
1032 index, value);
1033 PrepareFrameState(store, expr->GetIdForElement(i));
1034 }
1035
1036 environment()->Pop(); // Array literal index.
1037 ast_context()->ProduceValue(environment()->Pop());
1038}
1039
1040
1041void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
1042 DCHECK(expr->IsValidReferenceExpression());
1043
1044 // Left-hand side can only be a property, a global or a variable slot.
1045 Property* property = expr->AsProperty();
1046 LhsKind assign_type = DetermineLhsKind(expr);
1047
1048 // Evaluate LHS expression and store the value.
1049 switch (assign_type) {
1050 case VARIABLE: {
1051 Variable* var = expr->AsVariableProxy()->var();
1052 // TODO(jarin) Fill in the correct bailout id.
1053 BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None());
1054 break;
1055 }
1056 case NAMED_PROPERTY: {
1057 environment()->Push(value);
1058 VisitForValue(property->obj());
1059 Node* object = environment()->Pop();
1060 value = environment()->Pop();
1061 Unique<Name> name =
1062 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1063 Node* store =
1064 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1065 // TODO(jarin) Fill in the correct bailout id.
1066 PrepareFrameState(store, BailoutId::None());
1067 break;
1068 }
1069 case KEYED_PROPERTY: {
1070 environment()->Push(value);
1071 VisitForValue(property->obj());
1072 VisitForValue(property->key());
1073 Node* key = environment()->Pop();
1074 Node* object = environment()->Pop();
1075 value = environment()->Pop();
1076 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1077 key, value);
1078 // TODO(jarin) Fill in the correct bailout id.
1079 PrepareFrameState(store, BailoutId::None());
1080 break;
1081 }
1082 }
1083}
1084
1085
1086void AstGraphBuilder::VisitAssignment(Assignment* expr) {
1087 DCHECK(expr->target()->IsValidReferenceExpression());
1088
1089 // Left-hand side can only be a property, a global or a variable slot.
1090 Property* property = expr->target()->AsProperty();
1091 LhsKind assign_type = DetermineLhsKind(expr->target());
1092
1093 // Evaluate LHS expression.
1094 switch (assign_type) {
1095 case VARIABLE:
1096 // Nothing to do here.
1097 break;
1098 case NAMED_PROPERTY:
1099 VisitForValue(property->obj());
1100 break;
1101 case KEYED_PROPERTY: {
1102 VisitForValue(property->obj());
1103 VisitForValue(property->key());
1104 break;
1105 }
1106 }
1107
1108 // Evaluate the value and potentially handle compound assignments by loading
1109 // the left-hand side value and performing a binary operation.
1110 if (expr->is_compound()) {
1111 Node* old_value = NULL;
1112 switch (assign_type) {
1113 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001114 VariableProxy* proxy = expr->target()->AsVariableProxy();
1115 VectorSlotPair pair =
1116 CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1117 old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 break;
1119 }
1120 case NAMED_PROPERTY: {
1121 Node* object = environment()->Top();
1122 Unique<Name> name =
1123 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001124 VectorSlotPair pair =
1125 CreateVectorSlotPair(property->PropertyFeedbackSlot());
1126 old_value = NewNode(javascript()->LoadNamed(name, pair), object);
1127 PrepareFrameState(old_value, property->LoadId(),
1128 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 break;
1130 }
1131 case KEYED_PROPERTY: {
1132 Node* key = environment()->Top();
1133 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001134 VectorSlotPair pair =
1135 CreateVectorSlotPair(property->PropertyFeedbackSlot());
1136 old_value = NewNode(javascript()->LoadProperty(pair), object, key);
1137 PrepareFrameState(old_value, property->LoadId(),
1138 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001139 break;
1140 }
1141 }
1142 environment()->Push(old_value);
1143 VisitForValue(expr->value());
1144 Node* right = environment()->Pop();
1145 Node* left = environment()->Pop();
1146 Node* value = BuildBinaryOp(left, right, expr->binary_op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001147 PrepareFrameState(value, expr->binary_operation()->id(),
1148 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 environment()->Push(value);
1150 } else {
1151 VisitForValue(expr->value());
1152 }
1153
1154 // Store the value.
1155 Node* value = environment()->Pop();
1156 switch (assign_type) {
1157 case VARIABLE: {
1158 Variable* variable = expr->target()->AsVariableProxy()->var();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001159 BuildVariableAssignment(variable, value, expr->op(), expr->AssignmentId(),
1160 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 break;
1162 }
1163 case NAMED_PROPERTY: {
1164 Node* object = environment()->Pop();
1165 Unique<Name> name =
1166 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1167 Node* store =
1168 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001169 PrepareFrameState(store, expr->AssignmentId(),
1170 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001171 break;
1172 }
1173 case KEYED_PROPERTY: {
1174 Node* key = environment()->Pop();
1175 Node* object = environment()->Pop();
1176 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1177 key, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001178 PrepareFrameState(store, expr->AssignmentId(),
1179 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 break;
1181 }
1182 }
1183
1184 ast_context()->ProduceValue(value);
1185}
1186
1187
1188void AstGraphBuilder::VisitYield(Yield* expr) {
1189 VisitForValue(expr->generator_object());
1190 VisitForValue(expr->expression());
1191 environment()->Pop();
1192 environment()->Pop();
1193 // TODO(turbofan): VisitYield
1194 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1195}
1196
1197
1198void AstGraphBuilder::VisitThrow(Throw* expr) {
1199 VisitForValue(expr->exception());
1200 Node* exception = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001201 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 Node* value = NewNode(op, exception);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001203 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 ast_context()->ProduceValue(value);
1205}
1206
1207
1208void AstGraphBuilder::VisitProperty(Property* expr) {
1209 Node* value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001210 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211 if (expr->key()->IsPropertyName()) {
1212 VisitForValue(expr->obj());
1213 Node* object = environment()->Pop();
1214 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001215 value = NewNode(javascript()->LoadNamed(name, pair), object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 } else {
1217 VisitForValue(expr->obj());
1218 VisitForValue(expr->key());
1219 Node* key = environment()->Pop();
1220 Node* object = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 value = NewNode(javascript()->LoadProperty(pair), object, key);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001222 }
1223 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1224 ast_context()->ProduceValue(value);
1225}
1226
1227
1228void AstGraphBuilder::VisitCall(Call* expr) {
1229 Expression* callee = expr->expression();
1230 Call::CallType call_type = expr->GetCallType(isolate());
1231
1232 // Prepare the callee and the receiver to the function call. This depends on
1233 // the semantics of the underlying call type.
1234 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
1235 Node* receiver_value = NULL;
1236 Node* callee_value = NULL;
1237 bool possibly_eval = false;
1238 switch (call_type) {
1239 case Call::GLOBAL_CALL: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001240 VariableProxy* proxy = callee->AsVariableProxy();
1241 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1242 callee_value =
1243 BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 receiver_value = jsgraph()->UndefinedConstant();
1245 break;
1246 }
1247 case Call::LOOKUP_SLOT_CALL: {
1248 Variable* variable = callee->AsVariableProxy()->var();
1249 DCHECK(variable->location() == Variable::LOOKUP);
1250 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001251 const Operator* op =
1252 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 Node* pair = NewNode(op, current_context(), name);
1254 callee_value = NewNode(common()->Projection(0), pair);
1255 receiver_value = NewNode(common()->Projection(1), pair);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001256
1257 PrepareFrameState(pair, expr->EvalOrLookupId(),
1258 OutputFrameStateCombine::Push(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 break;
1260 }
1261 case Call::PROPERTY_CALL: {
1262 Property* property = callee->AsProperty();
1263 VisitForValue(property->obj());
1264 Node* object = environment()->Top();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001265 VectorSlotPair pair =
1266 CreateVectorSlotPair(property->PropertyFeedbackSlot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 if (property->key()->IsPropertyName()) {
1268 Unique<Name> name =
1269 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001270 callee_value = NewNode(javascript()->LoadNamed(name, pair), object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 } else {
1272 VisitForValue(property->key());
1273 Node* key = environment()->Pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001274 callee_value = NewNode(javascript()->LoadProperty(pair), object, key);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001276 PrepareFrameState(callee_value, property->LoadId(),
1277 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278 receiver_value = environment()->Pop();
1279 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
1280 // object for sloppy callees. This could also be modeled explicitly here,
1281 // thereby obsoleting the need for a flag to the call operator.
1282 flags = CALL_AS_METHOD;
1283 break;
1284 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285 case Call::SUPER_CALL: {
1286 // todo(dslomov): implement super calls in turbofan.
1287 UNIMPLEMENTED();
1288 break;
1289 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001290 case Call::POSSIBLY_EVAL_CALL:
1291 possibly_eval = true;
1292 // Fall through.
1293 case Call::OTHER_CALL:
1294 VisitForValue(callee);
1295 callee_value = environment()->Pop();
1296 receiver_value = jsgraph()->UndefinedConstant();
1297 break;
1298 }
1299
1300 // The callee and the receiver both have to be pushed onto the operand stack
1301 // before arguments are being evaluated.
1302 environment()->Push(callee_value);
1303 environment()->Push(receiver_value);
1304
1305 // Evaluate all arguments to the function call,
1306 ZoneList<Expression*>* args = expr->arguments();
1307 VisitForValues(args);
1308
1309 // Resolve callee and receiver for a potential direct eval call. This block
1310 // will mutate the callee and receiver values pushed onto the environment.
1311 if (possibly_eval && args->length() > 0) {
1312 int arg_count = args->length();
1313
1314 // Extract callee and source string from the environment.
1315 Node* callee = environment()->Peek(arg_count + 1);
1316 Node* source = environment()->Peek(arg_count - 1);
1317
1318 // Create node to ask for help resolving potential eval call. This will
1319 // provide a fully resolved callee and the corresponding receiver.
1320 Node* function = GetFunctionClosure();
1321 Node* receiver = environment()->Lookup(info()->scope()->receiver());
1322 Node* strict = jsgraph()->Constant(strict_mode());
1323 Node* position = jsgraph()->Constant(info()->scope()->start_position());
1324 const Operator* op =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001325 javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 Node* pair =
1327 NewNode(op, callee, source, function, receiver, strict, position);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001328 PrepareFrameState(pair, expr->EvalOrLookupId(),
1329 OutputFrameStateCombine::PokeAt(arg_count + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 Node* new_callee = NewNode(common()->Projection(0), pair);
1331 Node* new_receiver = NewNode(common()->Projection(1), pair);
1332
1333 // Patch callee and receiver on the environment.
1334 environment()->Poke(arg_count + 1, new_callee);
1335 environment()->Poke(arg_count + 0, new_receiver);
1336 }
1337
1338 // Create node to perform the function call.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001339 const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 Node* value = ProcessArguments(call, args->length() + 2);
1341 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1342 ast_context()->ProduceValue(value);
1343}
1344
1345
1346void AstGraphBuilder::VisitCallNew(CallNew* expr) {
1347 VisitForValue(expr->expression());
1348
1349 // Evaluate all arguments to the construct call.
1350 ZoneList<Expression*>* args = expr->arguments();
1351 VisitForValues(args);
1352
1353 // Create node to perform the construct call.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001354 const Operator* call = javascript()->CallConstruct(args->length() + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 Node* value = ProcessArguments(call, args->length() + 1);
1356 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1357 ast_context()->ProduceValue(value);
1358}
1359
1360
1361void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
1362 Handle<String> name = expr->name();
1363
1364 // The callee and the receiver both have to be pushed onto the operand stack
1365 // before arguments are being evaluated.
1366 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
1367 Node* receiver_value = BuildLoadBuiltinsObject();
1368 Unique<String> unique = MakeUnique(name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001369 VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot());
1370 Node* callee_value =
1371 NewNode(javascript()->LoadNamed(unique, pair), receiver_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
1373 // refuses to optimize functions with jsruntime calls).
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001374 PrepareFrameState(callee_value, BailoutId::None(),
1375 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376 environment()->Push(callee_value);
1377 environment()->Push(receiver_value);
1378
1379 // Evaluate all arguments to the JS runtime call.
1380 ZoneList<Expression*>* args = expr->arguments();
1381 VisitForValues(args);
1382
1383 // Create node to perform the JS runtime call.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001384 const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385 Node* value = ProcessArguments(call, args->length() + 2);
1386 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1387 ast_context()->ProduceValue(value);
1388}
1389
1390
1391void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
1392 const Runtime::Function* function = expr->function();
1393
1394 // Handle calls to runtime functions implemented in JavaScript separately as
1395 // the call follows JavaScript ABI and the callee is statically unknown.
1396 if (expr->is_jsruntime()) {
1397 DCHECK(function == NULL && expr->name()->length() > 0);
1398 return VisitCallJSRuntime(expr);
1399 }
1400
1401 // Evaluate all arguments to the runtime call.
1402 ZoneList<Expression*>* args = expr->arguments();
1403 VisitForValues(args);
1404
1405 // Create node to perform the runtime call.
1406 Runtime::FunctionId functionId = function->function_id;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001407 const Operator* call = javascript()->CallRuntime(functionId, args->length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 Node* value = ProcessArguments(call, args->length());
1409 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1410 ast_context()->ProduceValue(value);
1411}
1412
1413
1414void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1415 switch (expr->op()) {
1416 case Token::DELETE:
1417 return VisitDelete(expr);
1418 case Token::VOID:
1419 return VisitVoid(expr);
1420 case Token::TYPEOF:
1421 return VisitTypeof(expr);
1422 case Token::NOT:
1423 return VisitNot(expr);
1424 default:
1425 UNREACHABLE();
1426 }
1427}
1428
1429
1430void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
1431 DCHECK(expr->expression()->IsValidReferenceExpression());
1432
1433 // Left-hand side can only be a property, a global or a variable slot.
1434 Property* property = expr->expression()->AsProperty();
1435 LhsKind assign_type = DetermineLhsKind(expr->expression());
1436
1437 // Reserve space for result of postfix operation.
1438 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
1439 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());
1440
1441 // Evaluate LHS expression and get old value.
1442 Node* old_value = NULL;
1443 int stack_depth = -1;
1444 switch (assign_type) {
1445 case VARIABLE: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001446 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1447 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1448 old_value =
1449 BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001450 stack_depth = 0;
1451 break;
1452 }
1453 case NAMED_PROPERTY: {
1454 VisitForValue(property->obj());
1455 Node* object = environment()->Top();
1456 Unique<Name> name =
1457 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001458 VectorSlotPair pair =
1459 CreateVectorSlotPair(property->PropertyFeedbackSlot());
1460 old_value = NewNode(javascript()->LoadNamed(name, pair), object);
1461 PrepareFrameState(old_value, property->LoadId(),
1462 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 stack_depth = 1;
1464 break;
1465 }
1466 case KEYED_PROPERTY: {
1467 VisitForValue(property->obj());
1468 VisitForValue(property->key());
1469 Node* key = environment()->Top();
1470 Node* object = environment()->Peek(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001471 VectorSlotPair pair =
1472 CreateVectorSlotPair(property->PropertyFeedbackSlot());
1473 old_value = NewNode(javascript()->LoadProperty(pair), object, key);
1474 PrepareFrameState(old_value, property->LoadId(),
1475 OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 stack_depth = 2;
1477 break;
1478 }
1479 }
1480
1481 // Convert old value into a number.
1482 old_value = NewNode(javascript()->ToNumber(), old_value);
1483
1484 // Save result for postfix expressions at correct stack depth.
1485 if (is_postfix) environment()->Poke(stack_depth, old_value);
1486
1487 // Create node to perform +1/-1 operation.
1488 Node* value =
1489 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
1490 // TODO(jarin) Insert proper bailout id here (will need to change
1491 // full code generator).
1492 PrepareFrameState(value, BailoutId::None());
1493
1494 // Store the value.
1495 switch (assign_type) {
1496 case VARIABLE: {
1497 Variable* variable = expr->expression()->AsVariableProxy()->var();
1498 environment()->Push(value);
1499 BuildVariableAssignment(variable, value, expr->op(),
1500 expr->AssignmentId());
1501 environment()->Pop();
1502 break;
1503 }
1504 case NAMED_PROPERTY: {
1505 Node* object = environment()->Pop();
1506 Unique<Name> name =
1507 MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1508 Node* store =
1509 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1510 environment()->Push(value);
1511 PrepareFrameState(store, expr->AssignmentId());
1512 environment()->Pop();
1513 break;
1514 }
1515 case KEYED_PROPERTY: {
1516 Node* key = environment()->Pop();
1517 Node* object = environment()->Pop();
1518 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1519 key, value);
1520 environment()->Push(value);
1521 PrepareFrameState(store, expr->AssignmentId());
1522 environment()->Pop();
1523 break;
1524 }
1525 }
1526
1527 // Restore old value for postfix expressions.
1528 if (is_postfix) value = environment()->Pop();
1529
1530 ast_context()->ProduceValue(value);
1531}
1532
1533
1534void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1535 switch (expr->op()) {
1536 case Token::COMMA:
1537 return VisitComma(expr);
1538 case Token::OR:
1539 case Token::AND:
1540 return VisitLogicalExpression(expr);
1541 default: {
1542 VisitForValue(expr->left());
1543 VisitForValue(expr->right());
1544 Node* right = environment()->Pop();
1545 Node* left = environment()->Pop();
1546 Node* value = BuildBinaryOp(left, right, expr->op());
1547 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1548 ast_context()->ProduceValue(value);
1549 }
1550 }
1551}
1552
1553
1554void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
1555 const Operator* op;
1556 switch (expr->op()) {
1557 case Token::EQ:
1558 op = javascript()->Equal();
1559 break;
1560 case Token::NE:
1561 op = javascript()->NotEqual();
1562 break;
1563 case Token::EQ_STRICT:
1564 op = javascript()->StrictEqual();
1565 break;
1566 case Token::NE_STRICT:
1567 op = javascript()->StrictNotEqual();
1568 break;
1569 case Token::LT:
1570 op = javascript()->LessThan();
1571 break;
1572 case Token::GT:
1573 op = javascript()->GreaterThan();
1574 break;
1575 case Token::LTE:
1576 op = javascript()->LessThanOrEqual();
1577 break;
1578 case Token::GTE:
1579 op = javascript()->GreaterThanOrEqual();
1580 break;
1581 case Token::INSTANCEOF:
1582 op = javascript()->InstanceOf();
1583 break;
1584 case Token::IN:
1585 op = javascript()->HasProperty();
1586 break;
1587 default:
1588 op = NULL;
1589 UNREACHABLE();
1590 }
1591 VisitForValue(expr->left());
1592 VisitForValue(expr->right());
1593 Node* right = environment()->Pop();
1594 Node* left = environment()->Pop();
1595 Node* value = NewNode(op, left, right);
1596 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1597 ast_context()->ProduceValue(value);
1598}
1599
1600
1601void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
1602 Node* value = GetFunctionClosure();
1603 ast_context()->ProduceValue(value);
1604}
1605
1606
1607void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
1608 UNREACHABLE();
1609}
1610
1611
1612void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
1613
1614
1615void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001616 DCHECK(globals()->empty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 AstVisitor::VisitDeclarations(declarations);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001618 if (globals()->empty()) return;
1619 int array_index = 0;
1620 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
1621 static_cast<int>(globals()->size()), TENURED);
1622 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
1624 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
1625 DeclareGlobalsStrictMode::encode(strict_mode());
1626 Node* flags = jsgraph()->Constant(encoded_flags);
1627 Node* pairs = jsgraph()->Constant(data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001628 const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001629 NewNode(op, current_context(), pairs, flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001630 globals()->clear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001631}
1632
1633
1634void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
1635 if (stmt == NULL) return;
1636 Visit(stmt);
1637}
1638
1639
1640void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
1641 LoopBuilder* loop, int drop_extra) {
1642 BreakableScope scope(this, stmt, loop, drop_extra);
1643 Visit(stmt->body());
1644}
1645
1646
1647void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
1648 Node* value;
1649 if (expr->expression()->IsVariableProxy()) {
1650 // Delete of an unqualified identifier is only allowed in classic mode but
1651 // deleting "this" is allowed in all language modes.
1652 Variable* variable = expr->expression()->AsVariableProxy()->var();
1653 DCHECK(strict_mode() == SLOPPY || variable->is_this());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001654 value = BuildVariableDelete(variable, expr->id(),
1655 ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001656 } else if (expr->expression()->IsProperty()) {
1657 Property* property = expr->expression()->AsProperty();
1658 VisitForValue(property->obj());
1659 VisitForValue(property->key());
1660 Node* key = environment()->Pop();
1661 Node* object = environment()->Pop();
1662 value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001663 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 } else {
1665 VisitForEffect(expr->expression());
1666 value = jsgraph()->TrueConstant();
1667 }
1668 ast_context()->ProduceValue(value);
1669}
1670
1671
1672void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
1673 VisitForEffect(expr->expression());
1674 Node* value = jsgraph()->UndefinedConstant();
1675 ast_context()->ProduceValue(value);
1676}
1677
1678
1679void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
1680 Node* operand;
1681 if (expr->expression()->IsVariableProxy()) {
1682 // Typeof does not throw a reference error on global variables, hence we
1683 // perform a non-contextual load in case the operand is a variable proxy.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001684 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1685 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1686 operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair,
1687 NOT_CONTEXTUAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 } else {
1689 VisitForValue(expr->expression());
1690 operand = environment()->Pop();
1691 }
1692 Node* value = NewNode(javascript()->TypeOf(), operand);
1693 ast_context()->ProduceValue(value);
1694}
1695
1696
1697void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
1698 VisitForValue(expr->expression());
1699 Node* operand = environment()->Pop();
1700 // TODO(mstarzinger): Possible optimization when we are in effect context.
1701 Node* value = NewNode(javascript()->UnaryNot(), operand);
1702 ast_context()->ProduceValue(value);
1703}
1704
1705
1706void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
1707 VisitForEffect(expr->left());
1708 Visit(expr->right());
1709 ast_context()->ReplaceValue();
1710}
1711
1712
1713void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
1714 bool is_logical_and = expr->op() == Token::AND;
1715 IfBuilder compare_if(this);
1716 VisitForValue(expr->left());
1717 Node* condition = environment()->Top();
1718 compare_if.If(BuildToBoolean(condition));
1719 compare_if.Then();
1720 if (is_logical_and) {
1721 environment()->Pop();
1722 Visit(expr->right());
1723 } else if (ast_context()->IsEffect()) {
1724 environment()->Pop();
1725 }
1726 compare_if.Else();
1727 if (!is_logical_and) {
1728 environment()->Pop();
1729 Visit(expr->right());
1730 } else if (ast_context()->IsEffect()) {
1731 environment()->Pop();
1732 }
1733 compare_if.End();
1734 ast_context()->ReplaceValue();
1735}
1736
1737
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001738StrictMode AstGraphBuilder::strict_mode() const {
1739 return info()->strict_mode();
1740}
1741
1742
1743VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
1744 FeedbackVectorICSlot slot) const {
1745 return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
1746}
1747
1748
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
1750 DCHECK(environment()->stack_height() >= arity);
1751 Node** all = info()->zone()->NewArray<Node*>(arity);
1752 for (int i = arity - 1; i >= 0; --i) {
1753 all[i] = environment()->Pop();
1754 }
1755 Node* value = NewNode(op, arity, all);
1756 return value;
1757}
1758
1759
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001760Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
1761 // Sloppy mode functions and builtins need to replace the receiver with the
1762 // global proxy when called as functions (without an explicit receiver
1763 // object). Otherwise there is nothing left to do here.
1764 if (info()->strict_mode() != SLOPPY || info()->is_native()) return receiver;
1765
1766 // There is no need to perform patching if the receiver is never used. Note
1767 // that scope predicates are purely syntactical, a call to eval might still
1768 // inspect the receiver value.
1769 if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() &&
1770 !info()->scope()->calls_sloppy_eval()) {
1771 return receiver;
1772 }
1773
1774 IfBuilder receiver_check(this);
1775 Node* undefined = jsgraph()->UndefinedConstant();
1776 Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
1777 receiver_check.If(check);
1778 receiver_check.Then();
1779 environment()->Push(BuildLoadGlobalProxy());
1780 receiver_check.Else();
1781 environment()->Push(receiver);
1782 receiver_check.End();
1783 return environment()->Pop();
1784}
1785
1786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001787Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
1788 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
1789 if (heap_slots <= 0) return context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790
1791 // Allocate a new local context.
1792 const Operator* op = javascript()->CreateFunctionContext();
1793 Node* local_context = NewNode(op, closure);
1794 set_current_context(local_context);
1795
1796 // Copy parameters into context if necessary.
1797 int num_parameters = info()->scope()->num_parameters();
1798 for (int i = 0; i < num_parameters; i++) {
1799 Variable* variable = info()->scope()->parameter(i);
1800 if (!variable->IsContextSlot()) continue;
1801 // Temporary parameter node. The parameter indices are shifted by 1
1802 // (receiver is parameter index -1 but environment index 0).
1803 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start());
1804 // Context variable (at bottom of the context chain).
1805 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope()));
1806 const Operator* op = javascript()->StoreContext(0, variable->index());
1807 NewNode(op, local_context, parameter);
1808 }
1809
1810 return local_context;
1811}
1812
1813
1814Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
1815 if (arguments == NULL) return NULL;
1816
1817 // Allocate and initialize a new arguments object.
1818 Node* callee = GetFunctionClosure();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001819 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001820 Node* object = NewNode(op, callee);
1821
1822 // Assign the object to the arguments variable.
1823 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
1824 // This should never lazy deopt, so it is fine to send invalid bailout id.
1825 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
1826
1827 return object;
1828}
1829
1830
1831Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
1832 Node* not_hole) {
1833 IfBuilder hole_check(this);
1834 Node* the_hole = jsgraph()->TheHoleConstant();
1835 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1836 hole_check.If(check);
1837 hole_check.Then();
1838 environment()->Push(for_hole);
1839 hole_check.Else();
1840 environment()->Push(not_hole);
1841 hole_check.End();
1842 return environment()->Pop();
1843}
1844
1845
1846Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001847 Node* not_hole,
1848 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001849 IfBuilder hole_check(this);
1850 Node* the_hole = jsgraph()->TheHoleConstant();
1851 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1852 hole_check.If(check);
1853 hole_check.Then();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001854 environment()->Push(BuildThrowReferenceError(variable, bailout_id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001855 hole_check.Else();
1856 environment()->Push(not_hole);
1857 hole_check.End();
1858 return environment()->Pop();
1859}
1860
1861
1862Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
1863 BailoutId bailout_id,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001864 const VectorSlotPair& feedback,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 ContextualMode contextual_mode) {
1866 Node* the_hole = jsgraph()->TheHoleConstant();
1867 VariableMode mode = variable->mode();
1868 switch (variable->location()) {
1869 case Variable::UNALLOCATED: {
1870 // Global var, const, or let variable.
1871 Node* global = BuildLoadGlobalObject();
1872 Unique<Name> name = MakeUnique(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001873 const Operator* op =
1874 javascript()->LoadNamed(name, feedback, contextual_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001875 Node* node = NewNode(op, global);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001876 PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001877 return node;
1878 }
1879 case Variable::PARAMETER:
1880 case Variable::LOCAL: {
1881 // Local var, const, or let variable.
1882 Node* value = environment()->Lookup(variable);
1883 if (mode == CONST_LEGACY) {
1884 // Perform check for uninitialized legacy const variables.
1885 if (value->op() == the_hole->op()) {
1886 value = jsgraph()->UndefinedConstant();
1887 } else if (value->opcode() == IrOpcode::kPhi) {
1888 Node* undefined = jsgraph()->UndefinedConstant();
1889 value = BuildHoleCheckSilent(value, undefined, value);
1890 }
1891 } else if (mode == LET || mode == CONST) {
1892 // Perform check for uninitialized let/const variables.
1893 if (value->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001894 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001895 } else if (value->opcode() == IrOpcode::kPhi) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001896 value = BuildHoleCheckThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001897 }
1898 }
1899 return value;
1900 }
1901 case Variable::CONTEXT: {
1902 // Context variable (potentially up the context chain).
1903 int depth = current_scope()->ContextChainLength(variable->scope());
1904 bool immutable = variable->maybe_assigned() == kNotAssigned;
1905 const Operator* op =
1906 javascript()->LoadContext(depth, variable->index(), immutable);
1907 Node* value = NewNode(op, current_context());
1908 // TODO(titzer): initialization checks are redundant for already
1909 // initialized immutable context loads, but only specialization knows.
1910 // Maybe specializer should be a parameter to the graph builder?
1911 if (mode == CONST_LEGACY) {
1912 // Perform check for uninitialized legacy const variables.
1913 Node* undefined = jsgraph()->UndefinedConstant();
1914 value = BuildHoleCheckSilent(value, undefined, value);
1915 } else if (mode == LET || mode == CONST) {
1916 // Perform check for uninitialized let/const variables.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001917 value = BuildHoleCheckThrow(value, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 }
1919 return value;
1920 }
1921 case Variable::LOOKUP: {
1922 // Dynamic lookup of context variable (anywhere in the chain).
1923 Node* name = jsgraph()->Constant(variable->name());
1924 Runtime::FunctionId function_id =
1925 (contextual_mode == CONTEXTUAL)
1926 ? Runtime::kLoadLookupSlot
1927 : Runtime::kLoadLookupSlotNoReferenceError;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001928 const Operator* op = javascript()->CallRuntime(function_id, 2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001929 Node* pair = NewNode(op, current_context(), name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001930 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001931 return NewNode(common()->Projection(0), pair);
1932 }
1933 }
1934 UNREACHABLE();
1935 return NULL;
1936}
1937
1938
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001939Node* AstGraphBuilder::BuildVariableDelete(
1940 Variable* variable, BailoutId bailout_id,
1941 OutputFrameStateCombine state_combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001942 switch (variable->location()) {
1943 case Variable::UNALLOCATED: {
1944 // Global var, const, or let variable.
1945 Node* global = BuildLoadGlobalObject();
1946 Node* name = jsgraph()->Constant(variable->name());
1947 const Operator* op = javascript()->DeleteProperty(strict_mode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001948 Node* result = NewNode(op, global, name);
1949 PrepareFrameState(result, bailout_id, state_combine);
1950 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001951 }
1952 case Variable::PARAMETER:
1953 case Variable::LOCAL:
1954 case Variable::CONTEXT:
1955 // Local var, const, or let variable or context variable.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001956 return jsgraph()->BooleanConstant(variable->is_this());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001957 case Variable::LOOKUP: {
1958 // Dynamic lookup of context variable (anywhere in the chain).
1959 Node* name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001960 const Operator* op =
1961 javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
1962 Node* result = NewNode(op, current_context(), name);
1963 PrepareFrameState(result, bailout_id, state_combine);
1964 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001965 }
1966 }
1967 UNREACHABLE();
1968 return NULL;
1969}
1970
1971
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001972Node* AstGraphBuilder::BuildVariableAssignment(
1973 Variable* variable, Node* value, Token::Value op, BailoutId bailout_id,
1974 OutputFrameStateCombine combine) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001975 Node* the_hole = jsgraph()->TheHoleConstant();
1976 VariableMode mode = variable->mode();
1977 switch (variable->location()) {
1978 case Variable::UNALLOCATED: {
1979 // Global var, const, or let variable.
1980 Node* global = BuildLoadGlobalObject();
1981 Unique<Name> name = MakeUnique(variable->name());
1982 const Operator* op = javascript()->StoreNamed(strict_mode(), name);
1983 Node* store = NewNode(op, global, value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001984 PrepareFrameState(store, bailout_id, combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001985 return store;
1986 }
1987 case Variable::PARAMETER:
1988 case Variable::LOCAL:
1989 // Local var, const, or let variable.
1990 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
1991 // Perform an initialization check for legacy const variables.
1992 Node* current = environment()->Lookup(variable);
1993 if (current->op() != the_hole->op()) {
1994 value = BuildHoleCheckSilent(current, value, current);
1995 }
1996 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001997 // Non-initializing assignments to legacy const is
1998 // - exception in strict mode.
1999 // - ignored in sloppy mode.
2000 if (strict_mode() == STRICT) {
2001 return BuildThrowConstAssignError(bailout_id);
2002 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002003 return value;
2004 } else if (mode == LET && op != Token::INIT_LET) {
2005 // Perform an initialization check for let declared variables.
2006 // Also note that the dynamic hole-check is only done to ensure that
2007 // this does not break in the presence of do-expressions within the
2008 // temporal dead zone of a let declared variable.
2009 Node* current = environment()->Lookup(variable);
2010 if (current->op() == the_hole->op()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002011 value = BuildThrowReferenceError(variable, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002012 } else if (value->opcode() == IrOpcode::kPhi) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002013 value = BuildHoleCheckThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002014 }
2015 } else if (mode == CONST && op != Token::INIT_CONST) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002016 // Non-initializing assignments to const is exception in all modes.
2017 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002018 }
2019 environment()->Bind(variable, value);
2020 return value;
2021 case Variable::CONTEXT: {
2022 // Context variable (potentially up the context chain).
2023 int depth = current_scope()->ContextChainLength(variable->scope());
2024 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
2025 // Perform an initialization check for legacy const variables.
2026 const Operator* op =
2027 javascript()->LoadContext(depth, variable->index(), false);
2028 Node* current = NewNode(op, current_context());
2029 value = BuildHoleCheckSilent(current, value, current);
2030 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002031 // Non-initializing assignments to legacy const is
2032 // - exception in strict mode.
2033 // - ignored in sloppy mode.
2034 if (strict_mode() == STRICT) {
2035 return BuildThrowConstAssignError(bailout_id);
2036 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002037 return value;
2038 } else if (mode == LET && op != Token::INIT_LET) {
2039 // Perform an initialization check for let declared variables.
2040 const Operator* op =
2041 javascript()->LoadContext(depth, variable->index(), false);
2042 Node* current = NewNode(op, current_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002043 value = BuildHoleCheckThrow(current, variable, value, bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002044 } else if (mode == CONST && op != Token::INIT_CONST) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002045 // Non-initializing assignments to const is exception in all modes.
2046 return BuildThrowConstAssignError(bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002047 }
2048 const Operator* op = javascript()->StoreContext(depth, variable->index());
2049 return NewNode(op, current_context(), value);
2050 }
2051 case Variable::LOOKUP: {
2052 // Dynamic lookup of context variable (anywhere in the chain).
2053 Node* name = jsgraph()->Constant(variable->name());
2054 Node* strict = jsgraph()->Constant(strict_mode());
2055 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
2056 // initializations of const declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002057 const Operator* op =
2058 javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
2059 Node* store = NewNode(op, value, current_context(), name, strict);
2060 PrepareFrameState(store, bailout_id, combine);
2061 return store;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062 }
2063 }
2064 UNREACHABLE();
2065 return NULL;
2066}
2067
2068
2069Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002070 Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
2071 jsgraph()->Int32Constant(offset - kHeapObjectTag));
2072 return field_load;
2073}
2074
2075
2076Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
2077 Node* global = BuildLoadGlobalObject();
2078 Node* builtins =
2079 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
2080 return builtins;
2081}
2082
2083
2084Node* AstGraphBuilder::BuildLoadGlobalObject() {
2085 Node* context = GetFunctionContext();
2086 const Operator* load_op =
2087 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true);
2088 return NewNode(load_op, context);
2089}
2090
2091
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002092Node* AstGraphBuilder::BuildLoadGlobalProxy() {
2093 Node* global = BuildLoadGlobalObject();
2094 Node* proxy =
2095 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset);
2096 return proxy;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002097}
2098
2099
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002100Node* AstGraphBuilder::BuildToBoolean(Node* input) {
2101 // TODO(titzer): this should be in a JSOperatorReducer.
2102 switch (input->opcode()) {
2103 case IrOpcode::kInt32Constant:
2104 return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0));
2105 case IrOpcode::kFloat64Constant:
2106 return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0));
2107 case IrOpcode::kNumberConstant:
2108 return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0));
2109 case IrOpcode::kHeapConstant: {
2110 Handle<Object> object = HeapObjectMatcher<Object>(input).Value().handle();
2111 if (object->IsTrue()) return jsgraph_->TrueConstant();
2112 if (object->IsFalse()) return jsgraph_->FalseConstant();
2113 // TODO(turbofan): other constants.
2114 break;
2115 }
2116 default:
2117 break;
2118 }
2119 if (NodeProperties::IsTyped(input)) {
2120 Type* upper = NodeProperties::GetBounds(input).upper;
2121 if (upper->Is(Type::Boolean())) return input;
2122 }
2123
2124 return NewNode(javascript()->ToBoolean(), input);
2125}
2126
2127
2128Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
2129 BailoutId bailout_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002130 // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
2131 Node* variable_name = jsgraph()->Constant(variable->name());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002132 const Operator* op =
2133 javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
2134 Node* call = NewNode(op, variable_name);
2135 PrepareFrameState(call, bailout_id);
2136 return call;
2137}
2138
2139
2140Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
2141 // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
2142 const Operator* op =
2143 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
2144 Node* call = NewNode(op);
2145 PrepareFrameState(call, bailout_id);
2146 return call;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002147}
2148
2149
2150Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
2151 const Operator* js_op;
2152 switch (op) {
2153 case Token::BIT_OR:
2154 js_op = javascript()->BitwiseOr();
2155 break;
2156 case Token::BIT_AND:
2157 js_op = javascript()->BitwiseAnd();
2158 break;
2159 case Token::BIT_XOR:
2160 js_op = javascript()->BitwiseXor();
2161 break;
2162 case Token::SHL:
2163 js_op = javascript()->ShiftLeft();
2164 break;
2165 case Token::SAR:
2166 js_op = javascript()->ShiftRight();
2167 break;
2168 case Token::SHR:
2169 js_op = javascript()->ShiftRightLogical();
2170 break;
2171 case Token::ADD:
2172 js_op = javascript()->Add();
2173 break;
2174 case Token::SUB:
2175 js_op = javascript()->Subtract();
2176 break;
2177 case Token::MUL:
2178 js_op = javascript()->Multiply();
2179 break;
2180 case Token::DIV:
2181 js_op = javascript()->Divide();
2182 break;
2183 case Token::MOD:
2184 js_op = javascript()->Modulus();
2185 break;
2186 default:
2187 UNREACHABLE();
2188 js_op = NULL;
2189 }
2190 return NewNode(js_op, left, right);
2191}
2192
2193
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002194Node* AstGraphBuilder::BuildStackCheck() {
2195 IfBuilder stack_check(this);
2196 Node* limit =
2197 NewNode(jsgraph()->machine()->Load(kMachPtr),
2198 jsgraph()->ExternalConstant(
2199 ExternalReference::address_of_stack_limit(isolate())),
2200 jsgraph()->ZeroConstant());
2201 Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer());
2202 Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack);
2203 stack_check.If(tag, BranchHint::kTrue);
2204 stack_check.Then();
2205 stack_check.Else();
2206 Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
2207 stack_check.End();
2208 return guard;
2209}
2210
2211
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002212void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
2213 OutputFrameStateCombine combine) {
2214 if (OperatorProperties::HasFrameStateInput(node->op())) {
2215 DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() ==
2216 IrOpcode::kDead);
2217 NodeProperties::ReplaceFrameStateInput(
2218 node, environment()->Checkpoint(ast_id, combine));
2219 }
2220}
2221
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002222
2223BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
2224 IterationStatement* stmt) {
2225 if (loop_assignment_analysis_ == NULL) return NULL;
2226 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002227}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002228
2229} // namespace compiler
2230} // namespace internal
2231} // namespace v8