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
16namespace v8 {
17namespace internal {
18namespace compiler {
19
20AstGraphBuilder::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
31Node* 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
42Node* 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
53bool 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.
117enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
118
119
120// Determine the left-hand side kind of an assignment.
121static 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.
134static 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
152StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment(
153    StructuredGraphBuilder::Environment* env) {
154  return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
155}
156
157
158AstGraphBuilder::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
188AstGraphBuilder::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
198void 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
220Node* 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
235AstGraphBuilder::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
245AstGraphBuilder::AstContext::~AstContext() {
246  owner()->set_ast_context(outer_);  // Pop.
247}
248
249
250AstGraphBuilder::AstEffectContext::~AstEffectContext() {
251  DCHECK(environment()->stack_height() == original_height_);
252}
253
254
255AstGraphBuilder::AstValueContext::~AstValueContext() {
256  DCHECK(environment()->stack_height() == original_height_ + 1);
257}
258
259
260AstGraphBuilder::AstTestContext::~AstTestContext() {
261  DCHECK(environment()->stack_height() == original_height_ + 1);
262}
263
264
265void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
266  // The value is ignored.
267}
268
269
270void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
271  environment()->Push(value);
272}
273
274
275void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
276  environment()->Push(owner()->BuildToBoolean(value));
277}
278
279
280Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
281
282
283Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
284  return environment()->Pop();
285}
286
287
288Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
289  return environment()->Pop();
290}
291
292
293AstGraphBuilder::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
305void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) {
306  FindBreakable(stmt)->control_->Break();
307}
308
309
310void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) {
311  FindBreakable(stmt)->control_->Continue();
312}
313
314
315void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
316  if (expr == NULL) {
317    return environment()->Push(jsgraph()->NullConstant());
318  }
319  VisitForValue(expr);
320}
321
322
323void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
324  for (int i = 0; i < exprs->length(); ++i) {
325    VisitForValue(exprs->at(i));
326  }
327}
328
329
330void AstGraphBuilder::VisitForValue(Expression* expr) {
331  AstValueContext for_value(this);
332  if (!HasStackOverflow()) {
333    expr->Accept(this);
334  }
335}
336
337
338void AstGraphBuilder::VisitForEffect(Expression* expr) {
339  AstEffectContext for_effect(this);
340  if (!HasStackOverflow()) {
341    expr->Accept(this);
342  }
343}
344
345
346void AstGraphBuilder::VisitForTest(Expression* expr) {
347  AstTestContext for_condition(this);
348  if (!HasStackOverflow()) {
349    expr->Accept(this);
350  }
351}
352
353
354void 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
387void 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
419void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
420  UNREACHABLE();
421}
422
423
424void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
425  UNREACHABLE();
426}
427
428
429void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
430  UNREACHABLE();
431}
432
433
434void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }
435
436
437void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) {
438  UNREACHABLE();
439}
440
441
442void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
443
444
445void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
446
447
448void 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
469void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
470  UNREACHABLE();
471}
472
473
474void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
475  VisitForEffect(stmt->expression());
476}
477
478
479void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
480  // Do nothing.
481}
482
483
484void 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
497void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
498  StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
499  breakable()->ContinueTarget(stmt->target());
500  set_environment(env);
501}
502
503
504void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
505  StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
506  breakable()->BreakTarget(stmt->target());
507  set_environment(env);
508}
509
510
511void 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
519void 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
529void 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
581void 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
593void 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
605void 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.
622void 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
769void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
770  VisitForValue(stmt->subject());
771  environment()->Pop();
772  // TODO(turbofan): create and use loop builder.
773}
774
775
776void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
777  UNREACHABLE();
778}
779
780
781void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
782  UNREACHABLE();
783}
784
785
786void 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
793void 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
815void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
816  // TODO(arv): Implement.
817  UNREACHABLE();
818}
819
820
821void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
822  UNREACHABLE();
823}
824
825
826void 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
840void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
841  Node* value = BuildVariableLoad(expr->var(), expr->id());
842  ast_context()->ProduceValue(value);
843}
844
845
846void AstGraphBuilder::VisitLiteral(Literal* expr) {
847  Node* value = jsgraph()->Constant(expr->value());
848  ast_context()->ProduceValue(value);
849}
850
851
852void 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
868void 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
979void 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
1016void 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
1061void 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
1152void 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
1162void 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
1171void 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
1190void 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
1292void 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
1307void 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
1334void 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
1357void 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
1373void 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
1469void 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
1489void 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
1536void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
1537  Node* value = GetFunctionClosure();
1538  ast_context()->ProduceValue(value);
1539}
1540
1541
1542void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
1543  UNREACHABLE();
1544}
1545
1546
1547void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
1548
1549
1550void 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
1568void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
1569  if (stmt == NULL) return;
1570  Visit(stmt);
1571}
1572
1573
1574void 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
1581void 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
1604void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
1605  VisitForEffect(expr->expression());
1606  Node* value = jsgraph()->UndefinedConstant();
1607  ast_context()->ProduceValue(value);
1608}
1609
1610
1611void 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
1628void 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
1637void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
1638  VisitForEffect(expr->left());
1639  Visit(expr->right());
1640  ast_context()->ReplaceValue();
1641}
1642
1643
1644void 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
1669Node* 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
1680Node* 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
1708Node* 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
1725Node* 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
1740Node* 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
1755Node* 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
1829Node* 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
1856Node* 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
1940Node* 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
1948Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
1949  Node* global = BuildLoadGlobalObject();
1950  Node* builtins =
1951      BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
1952  return builtins;
1953}
1954
1955
1956Node* 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
1964Node* AstGraphBuilder::BuildToBoolean(Node* value) {
1965  // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
1966  return NewNode(javascript()->ToBoolean(), value);
1967}
1968
1969
1970Node* 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
1978Node* 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
2022void 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