1 // 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"
8 #include "src/compiler/control-builders.h"
9 #include "src/compiler/machine-operator.h"
10 #include "src/compiler/node-properties.h"
11 #include "src/compiler/node-properties-inl.h"
12 #include "src/full-codegen.h"
13 #include "src/parser.h"
14 #include "src/scopes.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace compiler {
19 
AstGraphBuilder(CompilationInfo * info,JSGraph * jsgraph)20 AstGraphBuilder::AstGraphBuilder(CompilationInfo* info, JSGraph* jsgraph)
21     : StructuredGraphBuilder(jsgraph->graph(), jsgraph->common()),
22       info_(info),
23       jsgraph_(jsgraph),
24       globals_(0, info->zone()),
25       breakable_(NULL),
26       execution_context_(NULL) {
27   InitializeAstVisitor(info->zone());
28 }
29 
30 
GetFunctionClosure()31 Node* AstGraphBuilder::GetFunctionClosure() {
32   if (!function_closure_.is_set()) {
33     // Parameter -1 is special for the function closure
34     const Operator* op = common()->Parameter(-1);
35     Node* node = NewNode(op, graph()->start());
36     function_closure_.set(node);
37   }
38   return function_closure_.get();
39 }
40 
41 
GetFunctionContext()42 Node* AstGraphBuilder::GetFunctionContext() {
43   if (!function_context_.is_set()) {
44     // Parameter (arity + 1) is special for the outer context of the function
45     const Operator* op = common()->Parameter(info()->num_parameters() + 1);
46     Node* node = NewNode(op, graph()->start());
47     function_context_.set(node);
48   }
49   return function_context_.get();
50 }
51 
52 
CreateGraph()53 bool AstGraphBuilder::CreateGraph() {
54   Scope* scope = info()->scope();
55   DCHECK(graph() != NULL);
56 
57   // Set up the basic structure of the graph.
58   int parameter_count = info()->num_parameters();
59   graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));
60 
61   // Initialize the top-level environment.
62   Environment env(this, scope, graph()->start());
63   set_environment(&env);
64 
65   // Build node to initialize local function context.
66   Node* closure = GetFunctionClosure();
67   Node* outer = GetFunctionContext();
68   Node* inner = BuildLocalFunctionContext(outer, closure);
69 
70   // Push top-level function scope for the function body.
71   ContextScope top_context(this, scope, inner);
72 
73   // Build the arguments object if it is used.
74   BuildArgumentsObject(scope->arguments());
75 
76   // Emit tracing call if requested to do so.
77   if (FLAG_trace) {
78     NewNode(javascript()->Runtime(Runtime::kTraceEnter, 0));
79   }
80 
81   // Visit implicit declaration of the function name.
82   if (scope->is_function_scope() && scope->function() != NULL) {
83     VisitVariableDeclaration(scope->function());
84   }
85 
86   // Visit declarations within the function scope.
87   VisitDeclarations(scope->declarations());
88 
89   // TODO(mstarzinger): This should do an inlined stack check.
90   Node* node = NewNode(javascript()->Runtime(Runtime::kStackGuard, 0));
91   PrepareFrameState(node, BailoutId::FunctionEntry());
92 
93   // Visit statements in the function body.
94   VisitStatements(info()->function()->body());
95   if (HasStackOverflow()) return false;
96 
97   // Emit tracing call if requested to do so.
98   if (FLAG_trace) {
99     // TODO(mstarzinger): Only traces implicit return.
100     Node* return_value = jsgraph()->UndefinedConstant();
101     NewNode(javascript()->Runtime(Runtime::kTraceExit, 1), return_value);
102   }
103 
104   // Return 'undefined' in case we can fall off the end.
105   Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant());
106   UpdateControlDependencyToLeaveFunction(control);
107 
108   // Finish the basic structure of the graph.
109   environment()->UpdateControlDependency(exit_control());
110   graph()->SetEnd(NewNode(common()->End()));
111 
112   return true;
113 }
114 
115 
116 // Left-hand side can only be a property, a global or a variable slot.
117 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
118 
119 
120 // Determine the left-hand side kind of an assignment.
DetermineLhsKind(Expression * expr)121 static LhsKind DetermineLhsKind(Expression* expr) {
122   Property* property = expr->AsProperty();
123   DCHECK(expr->IsValidReferenceExpression());
124   LhsKind lhs_kind =
125       (property == NULL) ? VARIABLE : (property->key()->IsPropertyName())
126                                           ? NAMED_PROPERTY
127                                           : KEYED_PROPERTY;
128   return lhs_kind;
129 }
130 
131 
132 // Helper to find an existing shared function info in the baseline code for the
133 // given function literal. Used to canonicalize SharedFunctionInfo objects.
SearchSharedFunctionInfo(Code * unoptimized_code,FunctionLiteral * expr)134 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
135     Code* unoptimized_code, FunctionLiteral* expr) {
136   int start_position = expr->start_position();
137   for (RelocIterator it(unoptimized_code); !it.done(); it.next()) {
138     RelocInfo* rinfo = it.rinfo();
139     if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
140     Object* obj = rinfo->target_object();
141     if (obj->IsSharedFunctionInfo()) {
142       SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
143       if (shared->start_position() == start_position) {
144         return Handle<SharedFunctionInfo>(shared);
145       }
146     }
147   }
148   return Handle<SharedFunctionInfo>();
149 }
150 
151 
CopyEnvironment(StructuredGraphBuilder::Environment * env)152 StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment(
153     StructuredGraphBuilder::Environment* env) {
154   return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
155 }
156 
157 
Environment(AstGraphBuilder * builder,Scope * scope,Node * control_dependency)158 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
159                                           Scope* scope,
160                                           Node* control_dependency)
161     : StructuredGraphBuilder::Environment(builder, control_dependency),
162       parameters_count_(scope->num_parameters() + 1),
163       locals_count_(scope->num_stack_slots()),
164       parameters_node_(NULL),
165       locals_node_(NULL),
166       stack_node_(NULL) {
167   DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
168 
169   // Bind the receiver variable.
170   Node* receiver = builder->graph()->NewNode(common()->Parameter(0),
171                                              builder->graph()->start());
172   values()->push_back(receiver);
173 
174   // Bind all parameter variables. The parameter indices are shifted by 1
175   // (receiver is parameter index -1 but environment index 0).
176   for (int i = 0; i < scope->num_parameters(); ++i) {
177     Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1),
178                                                 builder->graph()->start());
179     values()->push_back(parameter);
180   }
181 
182   // Bind all local variables to undefined.
183   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
184   values()->insert(values()->end(), locals_count(), undefined_constant);
185 }
186 
187 
Environment(const Environment & copy)188 AstGraphBuilder::Environment::Environment(const Environment& copy)
189     : StructuredGraphBuilder::Environment(
190           static_cast<StructuredGraphBuilder::Environment>(copy)),
191       parameters_count_(copy.parameters_count_),
192       locals_count_(copy.locals_count_),
193       parameters_node_(copy.parameters_node_),
194       locals_node_(copy.locals_node_),
195       stack_node_(copy.stack_node_) {}
196 
197 
UpdateStateValues(Node ** state_values,int offset,int count)198 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
199                                                      int offset, int count) {
200   bool should_update = false;
201   Node** env_values = (count == 0) ? NULL : &values()->at(offset);
202   if (*state_values == NULL || (*state_values)->InputCount() != count) {
203     should_update = true;
204   } else {
205     DCHECK(static_cast<size_t>(offset + count) <= values()->size());
206     for (int i = 0; i < count; i++) {
207       if ((*state_values)->InputAt(i) != env_values[i]) {
208         should_update = true;
209         break;
210       }
211     }
212   }
213   if (should_update) {
214     const Operator* op = common()->StateValues(count);
215     (*state_values) = graph()->NewNode(op, count, env_values);
216   }
217 }
218 
219 
Checkpoint(BailoutId ast_id,OutputFrameStateCombine combine)220 Node* AstGraphBuilder::Environment::Checkpoint(
221     BailoutId ast_id, OutputFrameStateCombine combine) {
222   UpdateStateValues(&parameters_node_, 0, parameters_count());
223   UpdateStateValues(&locals_node_, parameters_count(), locals_count());
224   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
225                     stack_height());
226 
227   const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine);
228 
229   return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_,
230                           GetContext(),
231                           builder()->jsgraph()->UndefinedConstant());
232 }
233 
234 
AstContext(AstGraphBuilder * own,Expression::Context kind)235 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
236                                         Expression::Context kind)
237     : kind_(kind), owner_(own), outer_(own->ast_context()) {
238   owner()->set_ast_context(this);  // Push.
239 #ifdef DEBUG
240   original_height_ = environment()->stack_height();
241 #endif
242 }
243 
244 
~AstContext()245 AstGraphBuilder::AstContext::~AstContext() {
246   owner()->set_ast_context(outer_);  // Pop.
247 }
248 
249 
~AstEffectContext()250 AstGraphBuilder::AstEffectContext::~AstEffectContext() {
251   DCHECK(environment()->stack_height() == original_height_);
252 }
253 
254 
~AstValueContext()255 AstGraphBuilder::AstValueContext::~AstValueContext() {
256   DCHECK(environment()->stack_height() == original_height_ + 1);
257 }
258 
259 
~AstTestContext()260 AstGraphBuilder::AstTestContext::~AstTestContext() {
261   DCHECK(environment()->stack_height() == original_height_ + 1);
262 }
263 
264 
ProduceValue(Node * value)265 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
266   // The value is ignored.
267 }
268 
269 
ProduceValue(Node * value)270 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
271   environment()->Push(value);
272 }
273 
274 
ProduceValue(Node * value)275 void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
276   environment()->Push(owner()->BuildToBoolean(value));
277 }
278 
279 
ConsumeValue()280 Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
281 
282 
ConsumeValue()283 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
284   return environment()->Pop();
285 }
286 
287 
ConsumeValue()288 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
289   return environment()->Pop();
290 }
291 
292 
FindBreakable(BreakableStatement * target)293 AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable(
294     BreakableStatement* target) {
295   BreakableScope* current = this;
296   while (current != NULL && current->target_ != target) {
297     owner_->environment()->Drop(current->drop_extra_);
298     current = current->next_;
299   }
300   DCHECK(current != NULL);  // Always found (unless stack is malformed).
301   return current;
302 }
303 
304 
BreakTarget(BreakableStatement * stmt)305 void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) {
306   FindBreakable(stmt)->control_->Break();
307 }
308 
309 
ContinueTarget(BreakableStatement * stmt)310 void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) {
311   FindBreakable(stmt)->control_->Continue();
312 }
313 
314 
VisitForValueOrNull(Expression * expr)315 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
316   if (expr == NULL) {
317     return environment()->Push(jsgraph()->NullConstant());
318   }
319   VisitForValue(expr);
320 }
321 
322 
VisitForValues(ZoneList<Expression * > * exprs)323 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
324   for (int i = 0; i < exprs->length(); ++i) {
325     VisitForValue(exprs->at(i));
326   }
327 }
328 
329 
VisitForValue(Expression * expr)330 void AstGraphBuilder::VisitForValue(Expression* expr) {
331   AstValueContext for_value(this);
332   if (!HasStackOverflow()) {
333     expr->Accept(this);
334   }
335 }
336 
337 
VisitForEffect(Expression * expr)338 void AstGraphBuilder::VisitForEffect(Expression* expr) {
339   AstEffectContext for_effect(this);
340   if (!HasStackOverflow()) {
341     expr->Accept(this);
342   }
343 }
344 
345 
VisitForTest(Expression * expr)346 void AstGraphBuilder::VisitForTest(Expression* expr) {
347   AstTestContext for_condition(this);
348   if (!HasStackOverflow()) {
349     expr->Accept(this);
350   }
351 }
352 
353 
VisitVariableDeclaration(VariableDeclaration * decl)354 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
355   Variable* variable = decl->proxy()->var();
356   VariableMode mode = decl->mode();
357   bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
358   switch (variable->location()) {
359     case Variable::UNALLOCATED: {
360       Handle<Oddball> value = variable->binding_needs_init()
361                                   ? isolate()->factory()->the_hole_value()
362                                   : isolate()->factory()->undefined_value();
363       globals()->Add(variable->name(), zone());
364       globals()->Add(value, zone());
365       break;
366     }
367     case Variable::PARAMETER:
368     case Variable::LOCAL:
369       if (hole_init) {
370         Node* value = jsgraph()->TheHoleConstant();
371         environment()->Bind(variable, value);
372       }
373       break;
374     case Variable::CONTEXT:
375       if (hole_init) {
376         Node* value = jsgraph()->TheHoleConstant();
377         const Operator* op = javascript()->StoreContext(0, variable->index());
378         NewNode(op, current_context(), value);
379       }
380       break;
381     case Variable::LOOKUP:
382       UNIMPLEMENTED();
383   }
384 }
385 
386 
VisitFunctionDeclaration(FunctionDeclaration * decl)387 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
388   Variable* variable = decl->proxy()->var();
389   switch (variable->location()) {
390     case Variable::UNALLOCATED: {
391       Handle<SharedFunctionInfo> function =
392           Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info());
393       // Check for stack-overflow exception.
394       if (function.is_null()) return SetStackOverflow();
395       globals()->Add(variable->name(), zone());
396       globals()->Add(function, zone());
397       break;
398     }
399     case Variable::PARAMETER:
400     case Variable::LOCAL: {
401       VisitForValue(decl->fun());
402       Node* value = environment()->Pop();
403       environment()->Bind(variable, value);
404       break;
405     }
406     case Variable::CONTEXT: {
407       VisitForValue(decl->fun());
408       Node* value = environment()->Pop();
409       const Operator* op = javascript()->StoreContext(0, variable->index());
410       NewNode(op, current_context(), value);
411       break;
412     }
413     case Variable::LOOKUP:
414       UNIMPLEMENTED();
415   }
416 }
417 
418 
VisitModuleDeclaration(ModuleDeclaration * decl)419 void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
420   UNREACHABLE();
421 }
422 
423 
VisitImportDeclaration(ImportDeclaration * decl)424 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
425   UNREACHABLE();
426 }
427 
428 
VisitExportDeclaration(ExportDeclaration * decl)429 void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
430   UNREACHABLE();
431 }
432 
433 
VisitModuleLiteral(ModuleLiteral * modl)434 void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }
435 
436 
VisitModuleVariable(ModuleVariable * modl)437 void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) {
438   UNREACHABLE();
439 }
440 
441 
VisitModulePath(ModulePath * modl)442 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
443 
444 
VisitModuleUrl(ModuleUrl * modl)445 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
446 
447 
VisitBlock(Block * stmt)448 void AstGraphBuilder::VisitBlock(Block* stmt) {
449   BlockBuilder block(this);
450   BreakableScope scope(this, stmt, &block, 0);
451   if (stmt->labels() != NULL) block.BeginBlock();
452   if (stmt->scope() == NULL) {
453     // Visit statements in the same scope, no declarations.
454     VisitStatements(stmt->statements());
455   } else {
456     const Operator* op = javascript()->CreateBlockContext();
457     Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo());
458     Node* context = NewNode(op, scope_info, GetFunctionClosure());
459     ContextScope scope(this, stmt->scope(), context);
460 
461     // Visit declarations and statements in a block scope.
462     VisitDeclarations(stmt->scope()->declarations());
463     VisitStatements(stmt->statements());
464   }
465   if (stmt->labels() != NULL) block.EndBlock();
466 }
467 
468 
VisitModuleStatement(ModuleStatement * stmt)469 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
470   UNREACHABLE();
471 }
472 
473 
VisitExpressionStatement(ExpressionStatement * stmt)474 void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
475   VisitForEffect(stmt->expression());
476 }
477 
478 
VisitEmptyStatement(EmptyStatement * stmt)479 void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
480   // Do nothing.
481 }
482 
483 
VisitIfStatement(IfStatement * stmt)484 void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
485   IfBuilder compare_if(this);
486   VisitForTest(stmt->condition());
487   Node* condition = environment()->Pop();
488   compare_if.If(condition);
489   compare_if.Then();
490   Visit(stmt->then_statement());
491   compare_if.Else();
492   Visit(stmt->else_statement());
493   compare_if.End();
494 }
495 
496 
VisitContinueStatement(ContinueStatement * stmt)497 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
498   StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
499   breakable()->ContinueTarget(stmt->target());
500   set_environment(env);
501 }
502 
503 
VisitBreakStatement(BreakStatement * stmt)504 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
505   StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
506   breakable()->BreakTarget(stmt->target());
507   set_environment(env);
508 }
509 
510 
VisitReturnStatement(ReturnStatement * stmt)511 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
512   VisitForValue(stmt->expression());
513   Node* result = environment()->Pop();
514   Node* control = NewNode(common()->Return(), result);
515   UpdateControlDependencyToLeaveFunction(control);
516 }
517 
518 
VisitWithStatement(WithStatement * stmt)519 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
520   VisitForValue(stmt->expression());
521   Node* value = environment()->Pop();
522   const Operator* op = javascript()->CreateWithContext();
523   Node* context = NewNode(op, value, GetFunctionClosure());
524   ContextScope scope(this, stmt->scope(), context);
525   Visit(stmt->statement());
526 }
527 
528 
VisitSwitchStatement(SwitchStatement * stmt)529 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
530   ZoneList<CaseClause*>* clauses = stmt->cases();
531   SwitchBuilder compare_switch(this, clauses->length());
532   BreakableScope scope(this, stmt, &compare_switch, 0);
533   compare_switch.BeginSwitch();
534   int default_index = -1;
535 
536   // Keep the switch value on the stack until a case matches.
537   VisitForValue(stmt->tag());
538   Node* tag = environment()->Top();
539 
540   // Iterate over all cases and create nodes for label comparison.
541   for (int i = 0; i < clauses->length(); i++) {
542     CaseClause* clause = clauses->at(i);
543 
544     // The default is not a test, remember index.
545     if (clause->is_default()) {
546       default_index = i;
547       continue;
548     }
549 
550     // Create nodes to perform label comparison as if via '==='. The switch
551     // value is still on the operand stack while the label is evaluated.
552     VisitForValue(clause->label());
553     Node* label = environment()->Pop();
554     const Operator* op = javascript()->StrictEqual();
555     Node* condition = NewNode(op, tag, label);
556     compare_switch.BeginLabel(i, condition);
557 
558     // Discard the switch value at label match.
559     environment()->Pop();
560     compare_switch.EndLabel();
561   }
562 
563   // Discard the switch value and mark the default case.
564   environment()->Pop();
565   if (default_index >= 0) {
566     compare_switch.DefaultAt(default_index);
567   }
568 
569   // Iterate over all cases and create nodes for case bodies.
570   for (int i = 0; i < clauses->length(); i++) {
571     CaseClause* clause = clauses->at(i);
572     compare_switch.BeginCase(i);
573     VisitStatements(clause->statements());
574     compare_switch.EndCase();
575   }
576 
577   compare_switch.EndSwitch();
578 }
579 
580 
VisitDoWhileStatement(DoWhileStatement * stmt)581 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
582   LoopBuilder while_loop(this);
583   while_loop.BeginLoop();
584   VisitIterationBody(stmt, &while_loop, 0);
585   while_loop.EndBody();
586   VisitForTest(stmt->cond());
587   Node* condition = environment()->Pop();
588   while_loop.BreakUnless(condition);
589   while_loop.EndLoop();
590 }
591 
592 
VisitWhileStatement(WhileStatement * stmt)593 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
594   LoopBuilder while_loop(this);
595   while_loop.BeginLoop();
596   VisitForTest(stmt->cond());
597   Node* condition = environment()->Pop();
598   while_loop.BreakUnless(condition);
599   VisitIterationBody(stmt, &while_loop, 0);
600   while_loop.EndBody();
601   while_loop.EndLoop();
602 }
603 
604 
VisitForStatement(ForStatement * stmt)605 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
606   LoopBuilder for_loop(this);
607   VisitIfNotNull(stmt->init());
608   for_loop.BeginLoop();
609   if (stmt->cond() != NULL) {
610     VisitForTest(stmt->cond());
611     Node* condition = environment()->Pop();
612     for_loop.BreakUnless(condition);
613   }
614   VisitIterationBody(stmt, &for_loop, 0);
615   for_loop.EndBody();
616   VisitIfNotNull(stmt->next());
617   for_loop.EndLoop();
618 }
619 
620 
621 // TODO(dcarney): this is a big function.  Try to clean up some.
VisitForInStatement(ForInStatement * stmt)622 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
623   VisitForValue(stmt->subject());
624   Node* obj = environment()->Pop();
625   // Check for undefined or null before entering loop.
626   IfBuilder is_undefined(this);
627   Node* is_undefined_cond =
628       NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant());
629   is_undefined.If(is_undefined_cond);
630   is_undefined.Then();
631   is_undefined.Else();
632   {
633     IfBuilder is_null(this);
634     Node* is_null_cond =
635         NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
636     is_null.If(is_null_cond);
637     is_null.Then();
638     is_null.Else();
639     // Convert object to jsobject.
640     // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
641     obj = NewNode(javascript()->ToObject(), obj);
642     environment()->Push(obj);
643     // TODO(dcarney): should do a fast enum cache check here to skip runtime.
644     environment()->Push(obj);
645     Node* cache_type = ProcessArguments(
646         javascript()->Runtime(Runtime::kGetPropertyNamesFast, 1), 1);
647     // TODO(dcarney): these next runtime calls should be removed in favour of
648     //                a few simplified instructions.
649     environment()->Push(obj);
650     environment()->Push(cache_type);
651     Node* cache_pair =
652         ProcessArguments(javascript()->Runtime(Runtime::kForInInit, 2), 2);
653     // cache_type may have been replaced.
654     Node* cache_array = NewNode(common()->Projection(0), cache_pair);
655     cache_type = NewNode(common()->Projection(1), cache_pair);
656     environment()->Push(cache_type);
657     environment()->Push(cache_array);
658     Node* cache_length = ProcessArguments(
659         javascript()->Runtime(Runtime::kForInCacheArrayLength, 2), 2);
660     {
661       // TODO(dcarney): this check is actually supposed to be for the
662       //                empty enum case only.
663       IfBuilder have_no_properties(this);
664       Node* empty_array_cond = NewNode(javascript()->StrictEqual(),
665                                        cache_length, jsgraph()->ZeroConstant());
666       have_no_properties.If(empty_array_cond);
667       have_no_properties.Then();
668       // Pop obj and skip loop.
669       environment()->Pop();
670       have_no_properties.Else();
671       {
672         // Construct the rest of the environment.
673         environment()->Push(cache_type);
674         environment()->Push(cache_array);
675         environment()->Push(cache_length);
676         environment()->Push(jsgraph()->ZeroConstant());
677         // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
678         LoopBuilder for_loop(this);
679         for_loop.BeginLoop();
680         // Check loop termination condition.
681         Node* index = environment()->Peek(0);
682         Node* exit_cond =
683             NewNode(javascript()->LessThan(), index, cache_length);
684         // TODO(jarin): provide real bailout id.
685         PrepareFrameState(exit_cond, BailoutId::None());
686         for_loop.BreakUnless(exit_cond);
687         // TODO(dcarney): this runtime call should be a handful of
688         //                simplified instructions that
689         //                basically produce
690         //                    value = array[index]
691         environment()->Push(obj);
692         environment()->Push(cache_array);
693         environment()->Push(cache_type);
694         environment()->Push(index);
695         Node* pair =
696             ProcessArguments(javascript()->Runtime(Runtime::kForInNext, 4), 4);
697         Node* value = NewNode(common()->Projection(0), pair);
698         Node* should_filter = NewNode(common()->Projection(1), pair);
699         environment()->Push(value);
700         {
701           // Test if FILTER_KEY needs to be called.
702           IfBuilder test_should_filter(this);
703           Node* should_filter_cond =
704               NewNode(javascript()->StrictEqual(), should_filter,
705                       jsgraph()->TrueConstant());
706           test_should_filter.If(should_filter_cond);
707           test_should_filter.Then();
708           value = environment()->Pop();
709           Node* builtins = BuildLoadBuiltinsObject();
710           Node* function = BuildLoadObjectField(
711               builtins,
712               JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
713           // Callee.
714           environment()->Push(function);
715           // Receiver.
716           environment()->Push(obj);
717           // Args.
718           environment()->Push(value);
719           // result is either the string key or Smi(0) indicating the property
720           // is gone.
721           Node* res = ProcessArguments(
722               javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
723           // TODO(jarin): provide real bailout id.
724           PrepareFrameState(res, BailoutId::None());
725           Node* property_missing = NewNode(javascript()->StrictEqual(), res,
726                                            jsgraph()->ZeroConstant());
727           {
728             IfBuilder is_property_missing(this);
729             is_property_missing.If(property_missing);
730             is_property_missing.Then();
731             // Inc counter and continue.
732             Node* index_inc =
733                 NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
734             // TODO(jarin): provide real bailout id.
735             PrepareFrameState(index_inc, BailoutId::None());
736             environment()->Poke(0, index_inc);
737             for_loop.Continue();
738             is_property_missing.Else();
739             is_property_missing.End();
740           }
741           // Replace 'value' in environment.
742           environment()->Push(res);
743           test_should_filter.Else();
744           test_should_filter.End();
745         }
746         value = environment()->Pop();
747         // Bind value and do loop body.
748         VisitForInAssignment(stmt->each(), value);
749         VisitIterationBody(stmt, &for_loop, 5);
750         for_loop.EndBody();
751         // Inc counter and continue.
752         Node* index_inc =
753             NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
754         // TODO(jarin): provide real bailout id.
755         PrepareFrameState(index_inc, BailoutId::None());
756         environment()->Poke(0, index_inc);
757         for_loop.EndLoop();
758         environment()->Drop(5);
759         // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
760       }
761       have_no_properties.End();
762     }
763     is_null.End();
764   }
765   is_undefined.End();
766 }
767 
768 
VisitForOfStatement(ForOfStatement * stmt)769 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
770   VisitForValue(stmt->subject());
771   environment()->Pop();
772   // TODO(turbofan): create and use loop builder.
773 }
774 
775 
VisitTryCatchStatement(TryCatchStatement * stmt)776 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
777   UNREACHABLE();
778 }
779 
780 
VisitTryFinallyStatement(TryFinallyStatement * stmt)781 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
782   UNREACHABLE();
783 }
784 
785 
VisitDebuggerStatement(DebuggerStatement * stmt)786 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
787   // TODO(turbofan): Do we really need a separate reloc-info for this?
788   Node* node = NewNode(javascript()->Runtime(Runtime::kDebugBreak, 0));
789   PrepareFrameState(node, stmt->DebugBreakId());
790 }
791 
792 
VisitFunctionLiteral(FunctionLiteral * expr)793 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
794   Node* context = current_context();
795 
796   // Build a new shared function info if we cannot find one in the baseline
797   // code. We also have a stack overflow if the recursive compilation did.
798   Handle<SharedFunctionInfo> shared_info =
799       SearchSharedFunctionInfo(info()->shared_info()->code(), expr);
800   if (shared_info.is_null()) {
801     shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info());
802     CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
803   }
804 
805   // Create node to instantiate a new closure.
806   Node* info = jsgraph()->Constant(shared_info);
807   Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant()
808                                       : jsgraph()->FalseConstant();
809   const Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3);
810   Node* value = NewNode(op, context, info, pretenure);
811   ast_context()->ProduceValue(value);
812 }
813 
814 
VisitClassLiteral(ClassLiteral * expr)815 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
816   // TODO(arv): Implement.
817   UNREACHABLE();
818 }
819 
820 
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)821 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
822   UNREACHABLE();
823 }
824 
825 
VisitConditional(Conditional * expr)826 void AstGraphBuilder::VisitConditional(Conditional* expr) {
827   IfBuilder compare_if(this);
828   VisitForTest(expr->condition());
829   Node* condition = environment()->Pop();
830   compare_if.If(condition);
831   compare_if.Then();
832   Visit(expr->then_expression());
833   compare_if.Else();
834   Visit(expr->else_expression());
835   compare_if.End();
836   ast_context()->ReplaceValue();
837 }
838 
839 
VisitVariableProxy(VariableProxy * expr)840 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
841   Node* value = BuildVariableLoad(expr->var(), expr->id());
842   ast_context()->ProduceValue(value);
843 }
844 
845 
VisitLiteral(Literal * expr)846 void AstGraphBuilder::VisitLiteral(Literal* expr) {
847   Node* value = jsgraph()->Constant(expr->value());
848   ast_context()->ProduceValue(value);
849 }
850 
851 
VisitRegExpLiteral(RegExpLiteral * expr)852 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
853   Node* closure = GetFunctionClosure();
854 
855   // Create node to materialize a regular expression literal.
856   Node* literals_array =
857       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
858   Node* literal_index = jsgraph()->Constant(expr->literal_index());
859   Node* pattern = jsgraph()->Constant(expr->pattern());
860   Node* flags = jsgraph()->Constant(expr->flags());
861   const Operator* op =
862       javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4);
863   Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
864   ast_context()->ProduceValue(literal);
865 }
866 
867 
VisitObjectLiteral(ObjectLiteral * expr)868 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
869   Node* closure = GetFunctionClosure();
870 
871   // Create node to deep-copy the literal boilerplate.
872   expr->BuildConstantProperties(isolate());
873   Node* literals_array =
874       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
875   Node* literal_index = jsgraph()->Constant(expr->literal_index());
876   Node* constants = jsgraph()->Constant(expr->constant_properties());
877   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
878   const Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4);
879   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
880 
881   // The object is expected on the operand stack during computation of the
882   // property values and is the value of the entire expression.
883   environment()->Push(literal);
884 
885   // Mark all computed expressions that are bound to a key that is shadowed by
886   // a later occurrence of the same key. For the marked expressions, no store
887   // code is emitted.
888   expr->CalculateEmitStore(zone());
889 
890   // Create nodes to store computed values into the literal.
891   AccessorTable accessor_table(zone());
892   for (int i = 0; i < expr->properties()->length(); i++) {
893     ObjectLiteral::Property* property = expr->properties()->at(i);
894     if (property->IsCompileTimeValue()) continue;
895 
896     Literal* key = property->key();
897     switch (property->kind()) {
898       case ObjectLiteral::Property::CONSTANT:
899         UNREACHABLE();
900       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
901         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
902       // Fall through.
903       case ObjectLiteral::Property::COMPUTED: {
904         // It is safe to use [[Put]] here because the boilerplate already
905         // contains computed properties with an uninitialized value.
906         if (key->value()->IsInternalizedString()) {
907           if (property->emit_store()) {
908             VisitForValue(property->value());
909             Node* value = environment()->Pop();
910             Unique<Name> name = MakeUnique(key->AsPropertyName());
911             Node* store = NewNode(javascript()->StoreNamed(strict_mode(), name),
912                                   literal, value);
913             PrepareFrameState(store, key->id());
914           } else {
915             VisitForEffect(property->value());
916           }
917           break;
918         }
919         environment()->Push(literal);  // Duplicate receiver.
920         VisitForValue(property->key());
921         VisitForValue(property->value());
922         Node* value = environment()->Pop();
923         Node* key = environment()->Pop();
924         Node* receiver = environment()->Pop();
925         if (property->emit_store()) {
926           Node* strict = jsgraph()->Constant(SLOPPY);
927           const Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4);
928           NewNode(op, receiver, key, value, strict);
929         }
930         break;
931       }
932       case ObjectLiteral::Property::PROTOTYPE: {
933         environment()->Push(literal);  // Duplicate receiver.
934         VisitForValue(property->value());
935         Node* value = environment()->Pop();
936         Node* receiver = environment()->Pop();
937         if (property->emit_store()) {
938           const Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2);
939           NewNode(op, receiver, value);
940         }
941         break;
942       }
943       case ObjectLiteral::Property::GETTER:
944         accessor_table.lookup(key)->second->getter = property->value();
945         break;
946       case ObjectLiteral::Property::SETTER:
947         accessor_table.lookup(key)->second->setter = property->value();
948         break;
949     }
950   }
951 
952   // Create nodes to define accessors, using only a single call to the runtime
953   // for each pair of corresponding getters and setters.
954   for (AccessorTable::Iterator it = accessor_table.begin();
955        it != accessor_table.end(); ++it) {
956     VisitForValue(it->first);
957     VisitForValueOrNull(it->second->getter);
958     VisitForValueOrNull(it->second->setter);
959     Node* setter = environment()->Pop();
960     Node* getter = environment()->Pop();
961     Node* name = environment()->Pop();
962     Node* attr = jsgraph()->Constant(NONE);
963     const Operator* op =
964         javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5);
965     Node* call = NewNode(op, literal, name, getter, setter, attr);
966     PrepareFrameState(call, it->first->id());
967   }
968 
969   // Transform literals that contain functions to fast properties.
970   if (expr->has_function()) {
971     const Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1);
972     NewNode(op, literal);
973   }
974 
975   ast_context()->ProduceValue(environment()->Pop());
976 }
977 
978 
VisitArrayLiteral(ArrayLiteral * expr)979 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
980   Node* closure = GetFunctionClosure();
981 
982   // Create node to deep-copy the literal boilerplate.
983   expr->BuildConstantElements(isolate());
984   Node* literals_array =
985       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
986   Node* literal_index = jsgraph()->Constant(expr->literal_index());
987   Node* constants = jsgraph()->Constant(expr->constant_elements());
988   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
989   const Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4);
990   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
991 
992   // The array and the literal index are both expected on the operand stack
993   // during computation of the element values.
994   environment()->Push(literal);
995   environment()->Push(literal_index);
996 
997   // Create nodes to evaluate all the non-constant subexpressions and to store
998   // them into the newly cloned array.
999   for (int i = 0; i < expr->values()->length(); i++) {
1000     Expression* subexpr = expr->values()->at(i);
1001     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1002 
1003     VisitForValue(subexpr);
1004     Node* value = environment()->Pop();
1005     Node* index = jsgraph()->Constant(i);
1006     Node* store = NewNode(javascript()->StoreProperty(strict_mode()), literal,
1007                           index, value);
1008     PrepareFrameState(store, expr->GetIdForElement(i));
1009   }
1010 
1011   environment()->Pop();  // Array literal index.
1012   ast_context()->ProduceValue(environment()->Pop());
1013 }
1014 
1015 
VisitForInAssignment(Expression * expr,Node * value)1016 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
1017   DCHECK(expr->IsValidReferenceExpression());
1018 
1019   // Left-hand side can only be a property, a global or a variable slot.
1020   Property* property = expr->AsProperty();
1021   LhsKind assign_type = DetermineLhsKind(expr);
1022 
1023   // Evaluate LHS expression and store the value.
1024   switch (assign_type) {
1025     case VARIABLE: {
1026       Variable* var = expr->AsVariableProxy()->var();
1027       // TODO(jarin) Fill in the correct bailout id.
1028       BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None());
1029       break;
1030     }
1031     case NAMED_PROPERTY: {
1032       environment()->Push(value);
1033       VisitForValue(property->obj());
1034       Node* object = environment()->Pop();
1035       value = environment()->Pop();
1036       Unique<Name> name =
1037           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1038       Node* store =
1039           NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1040       // TODO(jarin) Fill in the correct bailout id.
1041       PrepareFrameState(store, BailoutId::None());
1042       break;
1043     }
1044     case KEYED_PROPERTY: {
1045       environment()->Push(value);
1046       VisitForValue(property->obj());
1047       VisitForValue(property->key());
1048       Node* key = environment()->Pop();
1049       Node* object = environment()->Pop();
1050       value = environment()->Pop();
1051       Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1052                             key, value);
1053       // TODO(jarin) Fill in the correct bailout id.
1054       PrepareFrameState(store, BailoutId::None());
1055       break;
1056     }
1057   }
1058 }
1059 
1060 
VisitAssignment(Assignment * expr)1061 void AstGraphBuilder::VisitAssignment(Assignment* expr) {
1062   DCHECK(expr->target()->IsValidReferenceExpression());
1063 
1064   // Left-hand side can only be a property, a global or a variable slot.
1065   Property* property = expr->target()->AsProperty();
1066   LhsKind assign_type = DetermineLhsKind(expr->target());
1067 
1068   // Evaluate LHS expression.
1069   switch (assign_type) {
1070     case VARIABLE:
1071       // Nothing to do here.
1072       break;
1073     case NAMED_PROPERTY:
1074       VisitForValue(property->obj());
1075       break;
1076     case KEYED_PROPERTY: {
1077       VisitForValue(property->obj());
1078       VisitForValue(property->key());
1079       break;
1080     }
1081   }
1082 
1083   // Evaluate the value and potentially handle compound assignments by loading
1084   // the left-hand side value and performing a binary operation.
1085   if (expr->is_compound()) {
1086     Node* old_value = NULL;
1087     switch (assign_type) {
1088       case VARIABLE: {
1089         Variable* variable = expr->target()->AsVariableProxy()->var();
1090         old_value = BuildVariableLoad(variable, expr->target()->id());
1091         break;
1092       }
1093       case NAMED_PROPERTY: {
1094         Node* object = environment()->Top();
1095         Unique<Name> name =
1096             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1097         old_value = NewNode(javascript()->LoadNamed(name), object);
1098         PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1099         break;
1100       }
1101       case KEYED_PROPERTY: {
1102         Node* key = environment()->Top();
1103         Node* object = environment()->Peek(1);
1104         old_value = NewNode(javascript()->LoadProperty(), object, key);
1105         PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1106         break;
1107       }
1108     }
1109     environment()->Push(old_value);
1110     VisitForValue(expr->value());
1111     Node* right = environment()->Pop();
1112     Node* left = environment()->Pop();
1113     Node* value = BuildBinaryOp(left, right, expr->binary_op());
1114     PrepareFrameState(value, expr->binary_operation()->id(), kPushOutput);
1115     environment()->Push(value);
1116   } else {
1117     VisitForValue(expr->value());
1118   }
1119 
1120   // Store the value.
1121   Node* value = environment()->Pop();
1122   switch (assign_type) {
1123     case VARIABLE: {
1124       Variable* variable = expr->target()->AsVariableProxy()->var();
1125       BuildVariableAssignment(variable, value, expr->op(),
1126                               expr->AssignmentId());
1127       break;
1128     }
1129     case NAMED_PROPERTY: {
1130       Node* object = environment()->Pop();
1131       Unique<Name> name =
1132           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1133       Node* store =
1134           NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1135       PrepareFrameState(store, expr->AssignmentId());
1136       break;
1137     }
1138     case KEYED_PROPERTY: {
1139       Node* key = environment()->Pop();
1140       Node* object = environment()->Pop();
1141       Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1142                             key, value);
1143       PrepareFrameState(store, expr->AssignmentId());
1144       break;
1145     }
1146   }
1147 
1148   ast_context()->ProduceValue(value);
1149 }
1150 
1151 
VisitYield(Yield * expr)1152 void AstGraphBuilder::VisitYield(Yield* expr) {
1153   VisitForValue(expr->generator_object());
1154   VisitForValue(expr->expression());
1155   environment()->Pop();
1156   environment()->Pop();
1157   // TODO(turbofan): VisitYield
1158   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1159 }
1160 
1161 
VisitThrow(Throw * expr)1162 void AstGraphBuilder::VisitThrow(Throw* expr) {
1163   VisitForValue(expr->exception());
1164   Node* exception = environment()->Pop();
1165   const Operator* op = javascript()->Runtime(Runtime::kThrow, 1);
1166   Node* value = NewNode(op, exception);
1167   ast_context()->ProduceValue(value);
1168 }
1169 
1170 
VisitProperty(Property * expr)1171 void AstGraphBuilder::VisitProperty(Property* expr) {
1172   Node* value;
1173   if (expr->key()->IsPropertyName()) {
1174     VisitForValue(expr->obj());
1175     Node* object = environment()->Pop();
1176     Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
1177     value = NewNode(javascript()->LoadNamed(name), object);
1178   } else {
1179     VisitForValue(expr->obj());
1180     VisitForValue(expr->key());
1181     Node* key = environment()->Pop();
1182     Node* object = environment()->Pop();
1183     value = NewNode(javascript()->LoadProperty(), object, key);
1184   }
1185   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1186   ast_context()->ProduceValue(value);
1187 }
1188 
1189 
VisitCall(Call * expr)1190 void AstGraphBuilder::VisitCall(Call* expr) {
1191   Expression* callee = expr->expression();
1192   Call::CallType call_type = expr->GetCallType(isolate());
1193 
1194   // Prepare the callee and the receiver to the function call. This depends on
1195   // the semantics of the underlying call type.
1196   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
1197   Node* receiver_value = NULL;
1198   Node* callee_value = NULL;
1199   bool possibly_eval = false;
1200   switch (call_type) {
1201     case Call::GLOBAL_CALL: {
1202       Variable* variable = callee->AsVariableProxy()->var();
1203       callee_value = BuildVariableLoad(variable, expr->expression()->id());
1204       receiver_value = jsgraph()->UndefinedConstant();
1205       break;
1206     }
1207     case Call::LOOKUP_SLOT_CALL: {
1208       Variable* variable = callee->AsVariableProxy()->var();
1209       DCHECK(variable->location() == Variable::LOOKUP);
1210       Node* name = jsgraph()->Constant(variable->name());
1211       const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2);
1212       Node* pair = NewNode(op, current_context(), name);
1213       callee_value = NewNode(common()->Projection(0), pair);
1214       receiver_value = NewNode(common()->Projection(1), pair);
1215       break;
1216     }
1217     case Call::PROPERTY_CALL: {
1218       Property* property = callee->AsProperty();
1219       VisitForValue(property->obj());
1220       Node* object = environment()->Top();
1221       if (property->key()->IsPropertyName()) {
1222         Unique<Name> name =
1223             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1224         callee_value = NewNode(javascript()->LoadNamed(name), object);
1225       } else {
1226         VisitForValue(property->key());
1227         Node* key = environment()->Pop();
1228         callee_value = NewNode(javascript()->LoadProperty(), object, key);
1229       }
1230       PrepareFrameState(callee_value, property->LoadId(), kPushOutput);
1231       receiver_value = environment()->Pop();
1232       // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
1233       // object for sloppy callees. This could also be modeled explicitly here,
1234       // thereby obsoleting the need for a flag to the call operator.
1235       flags = CALL_AS_METHOD;
1236       break;
1237     }
1238     case Call::POSSIBLY_EVAL_CALL:
1239       possibly_eval = true;
1240     // Fall through.
1241     case Call::OTHER_CALL:
1242       VisitForValue(callee);
1243       callee_value = environment()->Pop();
1244       receiver_value = jsgraph()->UndefinedConstant();
1245       break;
1246   }
1247 
1248   // The callee and the receiver both have to be pushed onto the operand stack
1249   // before arguments are being evaluated.
1250   environment()->Push(callee_value);
1251   environment()->Push(receiver_value);
1252 
1253   // Evaluate all arguments to the function call,
1254   ZoneList<Expression*>* args = expr->arguments();
1255   VisitForValues(args);
1256 
1257   // Resolve callee and receiver for a potential direct eval call. This block
1258   // will mutate the callee and receiver values pushed onto the environment.
1259   if (possibly_eval && args->length() > 0) {
1260     int arg_count = args->length();
1261 
1262     // Extract callee and source string from the environment.
1263     Node* callee = environment()->Peek(arg_count + 1);
1264     Node* source = environment()->Peek(arg_count - 1);
1265 
1266     // Create node to ask for help resolving potential eval call. This will
1267     // provide a fully resolved callee and the corresponding receiver.
1268     Node* function = GetFunctionClosure();
1269     Node* receiver = environment()->Lookup(info()->scope()->receiver());
1270     Node* strict = jsgraph()->Constant(strict_mode());
1271     Node* position = jsgraph()->Constant(info()->scope()->start_position());
1272     const Operator* op =
1273         javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 6);
1274     Node* pair =
1275         NewNode(op, callee, source, function, receiver, strict, position);
1276     Node* new_callee = NewNode(common()->Projection(0), pair);
1277     Node* new_receiver = NewNode(common()->Projection(1), pair);
1278 
1279     // Patch callee and receiver on the environment.
1280     environment()->Poke(arg_count + 1, new_callee);
1281     environment()->Poke(arg_count + 0, new_receiver);
1282   }
1283 
1284   // Create node to perform the function call.
1285   const Operator* call = javascript()->Call(args->length() + 2, flags);
1286   Node* value = ProcessArguments(call, args->length() + 2);
1287   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1288   ast_context()->ProduceValue(value);
1289 }
1290 
1291 
VisitCallNew(CallNew * expr)1292 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
1293   VisitForValue(expr->expression());
1294 
1295   // Evaluate all arguments to the construct call.
1296   ZoneList<Expression*>* args = expr->arguments();
1297   VisitForValues(args);
1298 
1299   // Create node to perform the construct call.
1300   const Operator* call = javascript()->CallNew(args->length() + 1);
1301   Node* value = ProcessArguments(call, args->length() + 1);
1302   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1303   ast_context()->ProduceValue(value);
1304 }
1305 
1306 
VisitCallJSRuntime(CallRuntime * expr)1307 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
1308   Handle<String> name = expr->name();
1309 
1310   // The callee and the receiver both have to be pushed onto the operand stack
1311   // before arguments are being evaluated.
1312   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
1313   Node* receiver_value = BuildLoadBuiltinsObject();
1314   Unique<String> unique = MakeUnique(name);
1315   Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
1316   // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
1317   // refuses to optimize functions with jsruntime calls).
1318   PrepareFrameState(callee_value, BailoutId::None(), kPushOutput);
1319   environment()->Push(callee_value);
1320   environment()->Push(receiver_value);
1321 
1322   // Evaluate all arguments to the JS runtime call.
1323   ZoneList<Expression*>* args = expr->arguments();
1324   VisitForValues(args);
1325 
1326   // Create node to perform the JS runtime call.
1327   const Operator* call = javascript()->Call(args->length() + 2, flags);
1328   Node* value = ProcessArguments(call, args->length() + 2);
1329   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1330   ast_context()->ProduceValue(value);
1331 }
1332 
1333 
VisitCallRuntime(CallRuntime * expr)1334 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
1335   const Runtime::Function* function = expr->function();
1336 
1337   // Handle calls to runtime functions implemented in JavaScript separately as
1338   // the call follows JavaScript ABI and the callee is statically unknown.
1339   if (expr->is_jsruntime()) {
1340     DCHECK(function == NULL && expr->name()->length() > 0);
1341     return VisitCallJSRuntime(expr);
1342   }
1343 
1344   // Evaluate all arguments to the runtime call.
1345   ZoneList<Expression*>* args = expr->arguments();
1346   VisitForValues(args);
1347 
1348   // Create node to perform the runtime call.
1349   Runtime::FunctionId functionId = function->function_id;
1350   const Operator* call = javascript()->Runtime(functionId, args->length());
1351   Node* value = ProcessArguments(call, args->length());
1352   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1353   ast_context()->ProduceValue(value);
1354 }
1355 
1356 
VisitUnaryOperation(UnaryOperation * expr)1357 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1358   switch (expr->op()) {
1359     case Token::DELETE:
1360       return VisitDelete(expr);
1361     case Token::VOID:
1362       return VisitVoid(expr);
1363     case Token::TYPEOF:
1364       return VisitTypeof(expr);
1365     case Token::NOT:
1366       return VisitNot(expr);
1367     default:
1368       UNREACHABLE();
1369   }
1370 }
1371 
1372 
VisitCountOperation(CountOperation * expr)1373 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
1374   DCHECK(expr->expression()->IsValidReferenceExpression());
1375 
1376   // Left-hand side can only be a property, a global or a variable slot.
1377   Property* property = expr->expression()->AsProperty();
1378   LhsKind assign_type = DetermineLhsKind(expr->expression());
1379 
1380   // Reserve space for result of postfix operation.
1381   bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
1382   if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());
1383 
1384   // Evaluate LHS expression and get old value.
1385   Node* old_value = NULL;
1386   int stack_depth = -1;
1387   switch (assign_type) {
1388     case VARIABLE: {
1389       Variable* variable = expr->expression()->AsVariableProxy()->var();
1390       old_value = BuildVariableLoad(variable, expr->expression()->id());
1391       stack_depth = 0;
1392       break;
1393     }
1394     case NAMED_PROPERTY: {
1395       VisitForValue(property->obj());
1396       Node* object = environment()->Top();
1397       Unique<Name> name =
1398           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1399       old_value = NewNode(javascript()->LoadNamed(name), object);
1400       PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1401       stack_depth = 1;
1402       break;
1403     }
1404     case KEYED_PROPERTY: {
1405       VisitForValue(property->obj());
1406       VisitForValue(property->key());
1407       Node* key = environment()->Top();
1408       Node* object = environment()->Peek(1);
1409       old_value = NewNode(javascript()->LoadProperty(), object, key);
1410       PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1411       stack_depth = 2;
1412       break;
1413     }
1414   }
1415 
1416   // Convert old value into a number.
1417   old_value = NewNode(javascript()->ToNumber(), old_value);
1418 
1419   // Save result for postfix expressions at correct stack depth.
1420   if (is_postfix) environment()->Poke(stack_depth, old_value);
1421 
1422   // Create node to perform +1/-1 operation.
1423   Node* value =
1424       BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
1425   // TODO(jarin) Insert proper bailout id here (will need to change
1426   // full code generator).
1427   PrepareFrameState(value, BailoutId::None());
1428 
1429   // Store the value.
1430   switch (assign_type) {
1431     case VARIABLE: {
1432       Variable* variable = expr->expression()->AsVariableProxy()->var();
1433       environment()->Push(value);
1434       BuildVariableAssignment(variable, value, expr->op(),
1435                               expr->AssignmentId());
1436       environment()->Pop();
1437       break;
1438     }
1439     case NAMED_PROPERTY: {
1440       Node* object = environment()->Pop();
1441       Unique<Name> name =
1442           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1443       Node* store =
1444           NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1445       environment()->Push(value);
1446       PrepareFrameState(store, expr->AssignmentId());
1447       environment()->Pop();
1448       break;
1449     }
1450     case KEYED_PROPERTY: {
1451       Node* key = environment()->Pop();
1452       Node* object = environment()->Pop();
1453       Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1454                             key, value);
1455       environment()->Push(value);
1456       PrepareFrameState(store, expr->AssignmentId());
1457       environment()->Pop();
1458       break;
1459     }
1460   }
1461 
1462   // Restore old value for postfix expressions.
1463   if (is_postfix) value = environment()->Pop();
1464 
1465   ast_context()->ProduceValue(value);
1466 }
1467 
1468 
VisitBinaryOperation(BinaryOperation * expr)1469 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1470   switch (expr->op()) {
1471     case Token::COMMA:
1472       return VisitComma(expr);
1473     case Token::OR:
1474     case Token::AND:
1475       return VisitLogicalExpression(expr);
1476     default: {
1477       VisitForValue(expr->left());
1478       VisitForValue(expr->right());
1479       Node* right = environment()->Pop();
1480       Node* left = environment()->Pop();
1481       Node* value = BuildBinaryOp(left, right, expr->op());
1482       PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1483       ast_context()->ProduceValue(value);
1484     }
1485   }
1486 }
1487 
1488 
VisitCompareOperation(CompareOperation * expr)1489 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
1490   const Operator* op;
1491   switch (expr->op()) {
1492     case Token::EQ:
1493       op = javascript()->Equal();
1494       break;
1495     case Token::NE:
1496       op = javascript()->NotEqual();
1497       break;
1498     case Token::EQ_STRICT:
1499       op = javascript()->StrictEqual();
1500       break;
1501     case Token::NE_STRICT:
1502       op = javascript()->StrictNotEqual();
1503       break;
1504     case Token::LT:
1505       op = javascript()->LessThan();
1506       break;
1507     case Token::GT:
1508       op = javascript()->GreaterThan();
1509       break;
1510     case Token::LTE:
1511       op = javascript()->LessThanOrEqual();
1512       break;
1513     case Token::GTE:
1514       op = javascript()->GreaterThanOrEqual();
1515       break;
1516     case Token::INSTANCEOF:
1517       op = javascript()->InstanceOf();
1518       break;
1519     case Token::IN:
1520       op = javascript()->HasProperty();
1521       break;
1522     default:
1523       op = NULL;
1524       UNREACHABLE();
1525   }
1526   VisitForValue(expr->left());
1527   VisitForValue(expr->right());
1528   Node* right = environment()->Pop();
1529   Node* left = environment()->Pop();
1530   Node* value = NewNode(op, left, right);
1531   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1532   ast_context()->ProduceValue(value);
1533 }
1534 
1535 
VisitThisFunction(ThisFunction * expr)1536 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
1537   Node* value = GetFunctionClosure();
1538   ast_context()->ProduceValue(value);
1539 }
1540 
1541 
VisitSuperReference(SuperReference * expr)1542 void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
1543   UNREACHABLE();
1544 }
1545 
1546 
VisitCaseClause(CaseClause * expr)1547 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
1548 
1549 
VisitDeclarations(ZoneList<Declaration * > * declarations)1550 void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
1551   DCHECK(globals()->is_empty());
1552   AstVisitor::VisitDeclarations(declarations);
1553   if (globals()->is_empty()) return;
1554   Handle<FixedArray> data =
1555       isolate()->factory()->NewFixedArray(globals()->length(), TENURED);
1556   for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i));
1557   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
1558                       DeclareGlobalsNativeFlag::encode(info()->is_native()) |
1559                       DeclareGlobalsStrictMode::encode(strict_mode());
1560   Node* flags = jsgraph()->Constant(encoded_flags);
1561   Node* pairs = jsgraph()->Constant(data);
1562   const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3);
1563   NewNode(op, current_context(), pairs, flags);
1564   globals()->Rewind(0);
1565 }
1566 
1567 
VisitIfNotNull(Statement * stmt)1568 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
1569   if (stmt == NULL) return;
1570   Visit(stmt);
1571 }
1572 
1573 
VisitIterationBody(IterationStatement * stmt,LoopBuilder * loop,int drop_extra)1574 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
1575                                          LoopBuilder* loop, int drop_extra) {
1576   BreakableScope scope(this, stmt, loop, drop_extra);
1577   Visit(stmt->body());
1578 }
1579 
1580 
VisitDelete(UnaryOperation * expr)1581 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
1582   Node* value;
1583   if (expr->expression()->IsVariableProxy()) {
1584     // Delete of an unqualified identifier is only allowed in classic mode but
1585     // deleting "this" is allowed in all language modes.
1586     Variable* variable = expr->expression()->AsVariableProxy()->var();
1587     DCHECK(strict_mode() == SLOPPY || variable->is_this());
1588     value = BuildVariableDelete(variable);
1589   } else if (expr->expression()->IsProperty()) {
1590     Property* property = expr->expression()->AsProperty();
1591     VisitForValue(property->obj());
1592     VisitForValue(property->key());
1593     Node* key = environment()->Pop();
1594     Node* object = environment()->Pop();
1595     value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
1596   } else {
1597     VisitForEffect(expr->expression());
1598     value = jsgraph()->TrueConstant();
1599   }
1600   ast_context()->ProduceValue(value);
1601 }
1602 
1603 
VisitVoid(UnaryOperation * expr)1604 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
1605   VisitForEffect(expr->expression());
1606   Node* value = jsgraph()->UndefinedConstant();
1607   ast_context()->ProduceValue(value);
1608 }
1609 
1610 
VisitTypeof(UnaryOperation * expr)1611 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
1612   Node* operand;
1613   if (expr->expression()->IsVariableProxy()) {
1614     // Typeof does not throw a reference error on global variables, hence we
1615     // perform a non-contextual load in case the operand is a variable proxy.
1616     Variable* variable = expr->expression()->AsVariableProxy()->var();
1617     operand =
1618         BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
1619   } else {
1620     VisitForValue(expr->expression());
1621     operand = environment()->Pop();
1622   }
1623   Node* value = NewNode(javascript()->TypeOf(), operand);
1624   ast_context()->ProduceValue(value);
1625 }
1626 
1627 
VisitNot(UnaryOperation * expr)1628 void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
1629   VisitForValue(expr->expression());
1630   Node* operand = environment()->Pop();
1631   // TODO(mstarzinger): Possible optimization when we are in effect context.
1632   Node* value = NewNode(javascript()->UnaryNot(), operand);
1633   ast_context()->ProduceValue(value);
1634 }
1635 
1636 
VisitComma(BinaryOperation * expr)1637 void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
1638   VisitForEffect(expr->left());
1639   Visit(expr->right());
1640   ast_context()->ReplaceValue();
1641 }
1642 
1643 
VisitLogicalExpression(BinaryOperation * expr)1644 void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
1645   bool is_logical_and = expr->op() == Token::AND;
1646   IfBuilder compare_if(this);
1647   VisitForValue(expr->left());
1648   Node* condition = environment()->Top();
1649   compare_if.If(BuildToBoolean(condition));
1650   compare_if.Then();
1651   if (is_logical_and) {
1652     environment()->Pop();
1653     Visit(expr->right());
1654   } else if (ast_context()->IsEffect()) {
1655     environment()->Pop();
1656   }
1657   compare_if.Else();
1658   if (!is_logical_and) {
1659     environment()->Pop();
1660     Visit(expr->right());
1661   } else if (ast_context()->IsEffect()) {
1662     environment()->Pop();
1663   }
1664   compare_if.End();
1665   ast_context()->ReplaceValue();
1666 }
1667 
1668 
ProcessArguments(const Operator * op,int arity)1669 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
1670   DCHECK(environment()->stack_height() >= arity);
1671   Node** all = info()->zone()->NewArray<Node*>(arity);
1672   for (int i = arity - 1; i >= 0; --i) {
1673     all[i] = environment()->Pop();
1674   }
1675   Node* value = NewNode(op, arity, all);
1676   return value;
1677 }
1678 
1679 
BuildLocalFunctionContext(Node * context,Node * closure)1680 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
1681   int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
1682   if (heap_slots <= 0) return context;
1683   set_current_context(context);
1684 
1685   // Allocate a new local context.
1686   const Operator* op = javascript()->CreateFunctionContext();
1687   Node* local_context = NewNode(op, closure);
1688   set_current_context(local_context);
1689 
1690   // Copy parameters into context if necessary.
1691   int num_parameters = info()->scope()->num_parameters();
1692   for (int i = 0; i < num_parameters; i++) {
1693     Variable* variable = info()->scope()->parameter(i);
1694     if (!variable->IsContextSlot()) continue;
1695     // Temporary parameter node. The parameter indices are shifted by 1
1696     // (receiver is parameter index -1 but environment index 0).
1697     Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start());
1698     // Context variable (at bottom of the context chain).
1699     DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope()));
1700     const Operator* op = javascript()->StoreContext(0, variable->index());
1701     NewNode(op, local_context, parameter);
1702   }
1703 
1704   return local_context;
1705 }
1706 
1707 
BuildArgumentsObject(Variable * arguments)1708 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
1709   if (arguments == NULL) return NULL;
1710 
1711   // Allocate and initialize a new arguments object.
1712   Node* callee = GetFunctionClosure();
1713   const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1);
1714   Node* object = NewNode(op, callee);
1715 
1716   // Assign the object to the arguments variable.
1717   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
1718   // This should never lazy deopt, so it is fine to send invalid bailout id.
1719   BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
1720 
1721   return object;
1722 }
1723 
1724 
BuildHoleCheckSilent(Node * value,Node * for_hole,Node * not_hole)1725 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
1726                                             Node* not_hole) {
1727   IfBuilder hole_check(this);
1728   Node* the_hole = jsgraph()->TheHoleConstant();
1729   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1730   hole_check.If(check);
1731   hole_check.Then();
1732   environment()->Push(for_hole);
1733   hole_check.Else();
1734   environment()->Push(not_hole);
1735   hole_check.End();
1736   return environment()->Pop();
1737 }
1738 
1739 
BuildHoleCheckThrow(Node * value,Variable * variable,Node * not_hole)1740 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
1741                                            Node* not_hole) {
1742   IfBuilder hole_check(this);
1743   Node* the_hole = jsgraph()->TheHoleConstant();
1744   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1745   hole_check.If(check);
1746   hole_check.Then();
1747   environment()->Push(BuildThrowReferenceError(variable));
1748   hole_check.Else();
1749   environment()->Push(not_hole);
1750   hole_check.End();
1751   return environment()->Pop();
1752 }
1753 
1754 
BuildVariableLoad(Variable * variable,BailoutId bailout_id,ContextualMode contextual_mode)1755 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
1756                                          BailoutId bailout_id,
1757                                          ContextualMode contextual_mode) {
1758   Node* the_hole = jsgraph()->TheHoleConstant();
1759   VariableMode mode = variable->mode();
1760   switch (variable->location()) {
1761     case Variable::UNALLOCATED: {
1762       // Global var, const, or let variable.
1763       Node* global = BuildLoadGlobalObject();
1764       Unique<Name> name = MakeUnique(variable->name());
1765       const Operator* op = javascript()->LoadNamed(name, contextual_mode);
1766       Node* node = NewNode(op, global);
1767       PrepareFrameState(node, bailout_id, kPushOutput);
1768       return node;
1769     }
1770     case Variable::PARAMETER:
1771     case Variable::LOCAL: {
1772       // Local var, const, or let variable.
1773       Node* value = environment()->Lookup(variable);
1774       if (mode == CONST_LEGACY) {
1775         // Perform check for uninitialized legacy const variables.
1776         if (value->op() == the_hole->op()) {
1777           value = jsgraph()->UndefinedConstant();
1778         } else if (value->opcode() == IrOpcode::kPhi) {
1779           Node* undefined = jsgraph()->UndefinedConstant();
1780           value = BuildHoleCheckSilent(value, undefined, value);
1781         }
1782       } else if (mode == LET || mode == CONST) {
1783         // Perform check for uninitialized let/const variables.
1784         if (value->op() == the_hole->op()) {
1785           value = BuildThrowReferenceError(variable);
1786         } else if (value->opcode() == IrOpcode::kPhi) {
1787           value = BuildHoleCheckThrow(value, variable, value);
1788         }
1789       }
1790       return value;
1791     }
1792     case Variable::CONTEXT: {
1793       // Context variable (potentially up the context chain).
1794       int depth = current_scope()->ContextChainLength(variable->scope());
1795       bool immutable = variable->maybe_assigned() == kNotAssigned;
1796       const Operator* op =
1797           javascript()->LoadContext(depth, variable->index(), immutable);
1798       Node* value = NewNode(op, current_context());
1799       // TODO(titzer): initialization checks are redundant for already
1800       // initialized immutable context loads, but only specialization knows.
1801       // Maybe specializer should be a parameter to the graph builder?
1802       if (mode == CONST_LEGACY) {
1803         // Perform check for uninitialized legacy const variables.
1804         Node* undefined = jsgraph()->UndefinedConstant();
1805         value = BuildHoleCheckSilent(value, undefined, value);
1806       } else if (mode == LET || mode == CONST) {
1807         // Perform check for uninitialized let/const variables.
1808         value = BuildHoleCheckThrow(value, variable, value);
1809       }
1810       return value;
1811     }
1812     case Variable::LOOKUP: {
1813       // Dynamic lookup of context variable (anywhere in the chain).
1814       Node* name = jsgraph()->Constant(variable->name());
1815       Runtime::FunctionId function_id =
1816           (contextual_mode == CONTEXTUAL)
1817               ? Runtime::kLoadLookupSlot
1818               : Runtime::kLoadLookupSlotNoReferenceError;
1819       const Operator* op = javascript()->Runtime(function_id, 2);
1820       Node* pair = NewNode(op, current_context(), name);
1821       return NewNode(common()->Projection(0), pair);
1822     }
1823   }
1824   UNREACHABLE();
1825   return NULL;
1826 }
1827 
1828 
BuildVariableDelete(Variable * variable)1829 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
1830   switch (variable->location()) {
1831     case Variable::UNALLOCATED: {
1832       // Global var, const, or let variable.
1833       Node* global = BuildLoadGlobalObject();
1834       Node* name = jsgraph()->Constant(variable->name());
1835       const Operator* op = javascript()->DeleteProperty(strict_mode());
1836       return NewNode(op, global, name);
1837     }
1838     case Variable::PARAMETER:
1839     case Variable::LOCAL:
1840     case Variable::CONTEXT:
1841       // Local var, const, or let variable or context variable.
1842       return variable->is_this() ? jsgraph()->TrueConstant()
1843                                  : jsgraph()->FalseConstant();
1844     case Variable::LOOKUP: {
1845       // Dynamic lookup of context variable (anywhere in the chain).
1846       Node* name = jsgraph()->Constant(variable->name());
1847       const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2);
1848       return NewNode(op, current_context(), name);
1849     }
1850   }
1851   UNREACHABLE();
1852   return NULL;
1853 }
1854 
1855 
BuildVariableAssignment(Variable * variable,Node * value,Token::Value op,BailoutId bailout_id)1856 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
1857                                                Token::Value op,
1858                                                BailoutId bailout_id) {
1859   Node* the_hole = jsgraph()->TheHoleConstant();
1860   VariableMode mode = variable->mode();
1861   switch (variable->location()) {
1862     case Variable::UNALLOCATED: {
1863       // Global var, const, or let variable.
1864       Node* global = BuildLoadGlobalObject();
1865       Unique<Name> name = MakeUnique(variable->name());
1866       const Operator* op = javascript()->StoreNamed(strict_mode(), name);
1867       Node* store = NewNode(op, global, value);
1868       PrepareFrameState(store, bailout_id);
1869       return store;
1870     }
1871     case Variable::PARAMETER:
1872     case Variable::LOCAL:
1873       // Local var, const, or let variable.
1874       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
1875         // Perform an initialization check for legacy const variables.
1876         Node* current = environment()->Lookup(variable);
1877         if (current->op() != the_hole->op()) {
1878           value = BuildHoleCheckSilent(current, value, current);
1879         }
1880       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
1881         // Non-initializing assignments to legacy const is ignored.
1882         return value;
1883       } else if (mode == LET && op != Token::INIT_LET) {
1884         // Perform an initialization check for let declared variables.
1885         // Also note that the dynamic hole-check is only done to ensure that
1886         // this does not break in the presence of do-expressions within the
1887         // temporal dead zone of a let declared variable.
1888         Node* current = environment()->Lookup(variable);
1889         if (current->op() == the_hole->op()) {
1890           value = BuildThrowReferenceError(variable);
1891         } else if (value->opcode() == IrOpcode::kPhi) {
1892           value = BuildHoleCheckThrow(current, variable, value);
1893         }
1894       } else if (mode == CONST && op != Token::INIT_CONST) {
1895         // All assignments to const variables are early errors.
1896         UNREACHABLE();
1897       }
1898       environment()->Bind(variable, value);
1899       return value;
1900     case Variable::CONTEXT: {
1901       // Context variable (potentially up the context chain).
1902       int depth = current_scope()->ContextChainLength(variable->scope());
1903       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
1904         // Perform an initialization check for legacy const variables.
1905         const Operator* op =
1906             javascript()->LoadContext(depth, variable->index(), false);
1907         Node* current = NewNode(op, current_context());
1908         value = BuildHoleCheckSilent(current, value, current);
1909       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
1910         // Non-initializing assignments to legacy const is ignored.
1911         return value;
1912       } else if (mode == LET && op != Token::INIT_LET) {
1913         // Perform an initialization check for let declared variables.
1914         const Operator* op =
1915             javascript()->LoadContext(depth, variable->index(), false);
1916         Node* current = NewNode(op, current_context());
1917         value = BuildHoleCheckThrow(current, variable, value);
1918       } else if (mode == CONST && op != Token::INIT_CONST) {
1919         // All assignments to const variables are early errors.
1920         UNREACHABLE();
1921       }
1922       const Operator* op = javascript()->StoreContext(depth, variable->index());
1923       return NewNode(op, current_context(), value);
1924     }
1925     case Variable::LOOKUP: {
1926       // Dynamic lookup of context variable (anywhere in the chain).
1927       Node* name = jsgraph()->Constant(variable->name());
1928       Node* strict = jsgraph()->Constant(strict_mode());
1929       // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
1930       // initializations of const declarations.
1931       const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4);
1932       return NewNode(op, value, current_context(), name, strict);
1933     }
1934   }
1935   UNREACHABLE();
1936   return NULL;
1937 }
1938 
1939 
BuildLoadObjectField(Node * object,int offset)1940 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
1941   // TODO(sigurds) Use simplified load here once it is ready.
1942   Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
1943                              jsgraph()->Int32Constant(offset - kHeapObjectTag));
1944   return field_load;
1945 }
1946 
1947 
BuildLoadBuiltinsObject()1948 Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
1949   Node* global = BuildLoadGlobalObject();
1950   Node* builtins =
1951       BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
1952   return builtins;
1953 }
1954 
1955 
BuildLoadGlobalObject()1956 Node* AstGraphBuilder::BuildLoadGlobalObject() {
1957   Node* context = GetFunctionContext();
1958   const Operator* load_op =
1959       javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true);
1960   return NewNode(load_op, context);
1961 }
1962 
1963 
BuildToBoolean(Node * value)1964 Node* AstGraphBuilder::BuildToBoolean(Node* value) {
1965   // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
1966   return NewNode(javascript()->ToBoolean(), value);
1967 }
1968 
1969 
BuildThrowReferenceError(Variable * variable)1970 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
1971   // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
1972   Node* variable_name = jsgraph()->Constant(variable->name());
1973   const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1);
1974   return NewNode(op, variable_name);
1975 }
1976 
1977 
BuildBinaryOp(Node * left,Node * right,Token::Value op)1978 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
1979   const Operator* js_op;
1980   switch (op) {
1981     case Token::BIT_OR:
1982       js_op = javascript()->BitwiseOr();
1983       break;
1984     case Token::BIT_AND:
1985       js_op = javascript()->BitwiseAnd();
1986       break;
1987     case Token::BIT_XOR:
1988       js_op = javascript()->BitwiseXor();
1989       break;
1990     case Token::SHL:
1991       js_op = javascript()->ShiftLeft();
1992       break;
1993     case Token::SAR:
1994       js_op = javascript()->ShiftRight();
1995       break;
1996     case Token::SHR:
1997       js_op = javascript()->ShiftRightLogical();
1998       break;
1999     case Token::ADD:
2000       js_op = javascript()->Add();
2001       break;
2002     case Token::SUB:
2003       js_op = javascript()->Subtract();
2004       break;
2005     case Token::MUL:
2006       js_op = javascript()->Multiply();
2007       break;
2008     case Token::DIV:
2009       js_op = javascript()->Divide();
2010       break;
2011     case Token::MOD:
2012       js_op = javascript()->Modulus();
2013       break;
2014     default:
2015       UNREACHABLE();
2016       js_op = NULL;
2017   }
2018   return NewNode(js_op, left, right);
2019 }
2020 
2021 
PrepareFrameState(Node * node,BailoutId ast_id,OutputFrameStateCombine combine)2022 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
2023                                         OutputFrameStateCombine combine) {
2024   if (OperatorProperties::HasFrameStateInput(node->op())) {
2025     DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() ==
2026            IrOpcode::kDead);
2027     NodeProperties::ReplaceFrameStateInput(
2028         node, environment()->Checkpoint(ast_id, combine));
2029   }
2030 }
2031 
2032 }
2033 }
2034 }  // namespace v8::internal::compiler
2035