V8 Project
ast-graph-builder.cc
Go to the documentation of this file.
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 
6 
7 #include "src/compiler.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 
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 
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 
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 
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.
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.
88 
89  // TODO(mstarzinger): This should do an inlined stack check.
90  Node* node = NewNode(javascript()->Runtime(Runtime::kStackGuard, 0));
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());
107 
108  // Finish the basic structure of the graph.
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.
118 
119 
120 // Determine the left-hand side kind of an assignment.
122  Property* property = expr->AsProperty();
124  LhsKind lhs_kind =
125  (property == NULL) ? VARIABLE : (property->key()->IsPropertyName())
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.
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  }
149 }
150 
151 
154  return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
155 }
156 
157 
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 
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 
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 
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 
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 
245 AstGraphBuilder::AstContext::~AstContext() {
246  owner()->set_ast_context(outer_); // Pop.
247 }
248 
249 
250 AstGraphBuilder::AstEffectContext::~AstEffectContext() {
251  DCHECK(environment()->stack_height() == original_height_);
252 }
253 
254 
255 AstGraphBuilder::AstValueContext::~AstValueContext() {
256  DCHECK(environment()->stack_height() == original_height_ + 1);
257 }
258 
259 
260 AstGraphBuilder::AstTestContext::~AstTestContext() {
261  DCHECK(environment()->stack_height() == original_height_ + 1);
262 }
263 
264 
265 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
266  // The value is ignored.
267 }
268 
269 
270 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
271  environment()->Push(value);
272 }
273 
274 
275 void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
276  environment()->Push(owner()->BuildToBoolean(value));
277 }
278 
279 
280 Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
281 
282 
283 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
284  return environment()->Pop();
285 }
286 
287 
288 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
289  return environment()->Pop();
290 }
291 
292 
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 
305 void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) {
306  FindBreakable(stmt)->control_->Break();
307 }
308 
309 
310 void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) {
311  FindBreakable(stmt)->control_->Continue();
312 }
313 
314 
316  if (expr == NULL) {
317  return environment()->Push(jsgraph()->NullConstant());
318  }
319  VisitForValue(expr);
320 }
321 
322 
324  for (int i = 0; i < exprs->length(); ++i) {
325  VisitForValue(exprs->at(i));
326  }
327 }
328 
329 
331  AstValueContext for_value(this);
332  if (!HasStackOverflow()) {
333  expr->Accept(this);
334  }
335 }
336 
337 
339  AstEffectContext for_effect(this);
340  if (!HasStackOverflow()) {
341  expr->Accept(this);
342  }
343 }
344 
345 
347  AstTestContext for_condition(this);
348  if (!HasStackOverflow()) {
349  expr->Accept(this);
350  }
351 }
352 
353 
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 
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 
419 void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
420  UNREACHABLE();
421 }
422 
423 
424 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
425  UNREACHABLE();
426 }
427 
428 
429 void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
430  UNREACHABLE();
431 }
432 
433 
434 void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }
435 
436 
437 void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) {
438  UNREACHABLE();
439 }
440 
441 
442 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
443 
444 
445 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
446 
447 
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 
469 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
470  UNREACHABLE();
471 }
472 
473 
474 void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
475  VisitForEffect(stmt->expression());
476 }
477 
478 
479 void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
480  // Do nothing.
481 }
482 
483 
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 
497 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
499  breakable()->ContinueTarget(stmt->target());
500  set_environment(env);
501 }
502 
503 
504 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
506  breakable()->BreakTarget(stmt->target());
507  set_environment(env);
508 }
509 
510 
511 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
512  VisitForValue(stmt->expression());
513  Node* result = environment()->Pop();
514  Node* control = NewNode(common()->Return(), result);
516 }
517 
518 
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 
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 
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 
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 
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.
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.
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 
769 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
770  VisitForValue(stmt->subject());
771  environment()->Pop();
772  // TODO(turbofan): create and use loop builder.
773 }
774 
775 
776 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
777  UNREACHABLE();
778 }
779 
780 
781 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
782  UNREACHABLE();
783 }
784 
785 
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 
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 
815 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
816  // TODO(arv): Implement.
817  UNREACHABLE();
818 }
819 
820 
821 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
822  UNREACHABLE();
823 }
824 
825 
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 
840 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
841  Node* value = BuildVariableLoad(expr->var(), expr->id());
842  ast_context()->ProduceValue(value);
843 }
844 
845 
846 void AstGraphBuilder::VisitLiteral(Literal* expr) {
847  Node* value = jsgraph()->Constant(expr->value());
848  ast_context()->ProduceValue(value);
849 }
850 
851 
852 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
853  Node* closure = GetFunctionClosure();
854 
855  // Create node to materialize a regular expression literal.
856  Node* literals_array =
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 
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 =
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()) {
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 
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 =
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 
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.
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.
1055  break;
1056  }
1057  }
1058 }
1059 
1060 
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 
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 
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 
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 
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.
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.
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* receiver = environment()->Lookup(info()->scope()->receiver());
1269  Node* strict = jsgraph()->Constant(strict_mode());
1270  Node* position = jsgraph()->Constant(info()->scope()->start_position());
1271  const Operator* op =
1272  javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5);
1273  Node* pair = NewNode(op, callee, source, receiver, strict, position);
1274  Node* new_callee = NewNode(common()->Projection(0), pair);
1275  Node* new_receiver = NewNode(common()->Projection(1), pair);
1276 
1277  // Patch callee and receiver on the environment.
1278  environment()->Poke(arg_count + 1, new_callee);
1279  environment()->Poke(arg_count + 0, new_receiver);
1280  }
1281 
1282  // Create node to perform the function call.
1283  const Operator* call = javascript()->Call(args->length() + 2, flags);
1284  Node* value = ProcessArguments(call, args->length() + 2);
1285  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1286  ast_context()->ProduceValue(value);
1287 }
1288 
1289 
1290 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
1291  VisitForValue(expr->expression());
1292 
1293  // Evaluate all arguments to the construct call.
1294  ZoneList<Expression*>* args = expr->arguments();
1295  VisitForValues(args);
1296 
1297  // Create node to perform the construct call.
1298  const Operator* call = javascript()->CallNew(args->length() + 1);
1299  Node* value = ProcessArguments(call, args->length() + 1);
1300  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1301  ast_context()->ProduceValue(value);
1302 }
1303 
1304 
1305 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
1306  Handle<String> name = expr->name();
1307 
1308  // The callee and the receiver both have to be pushed onto the operand stack
1309  // before arguments are being evaluated.
1311  Node* receiver_value = BuildLoadBuiltinsObject();
1312  Unique<String> unique = MakeUnique(name);
1313  Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
1314  // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
1315  // refuses to optimize functions with jsruntime calls).
1316  PrepareFrameState(callee_value, BailoutId::None(), kPushOutput);
1317  environment()->Push(callee_value);
1318  environment()->Push(receiver_value);
1319 
1320  // Evaluate all arguments to the JS runtime call.
1321  ZoneList<Expression*>* args = expr->arguments();
1322  VisitForValues(args);
1323 
1324  // Create node to perform the JS runtime call.
1325  const Operator* call = javascript()->Call(args->length() + 2, flags);
1326  Node* value = ProcessArguments(call, args->length() + 2);
1327  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1328  ast_context()->ProduceValue(value);
1329 }
1330 
1331 
1332 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
1333  const Runtime::Function* function = expr->function();
1334 
1335  // Handle calls to runtime functions implemented in JavaScript separately as
1336  // the call follows JavaScript ABI and the callee is statically unknown.
1337  if (expr->is_jsruntime()) {
1338  DCHECK(function == NULL && expr->name()->length() > 0);
1339  return VisitCallJSRuntime(expr);
1340  }
1341 
1342  // Evaluate all arguments to the runtime call.
1343  ZoneList<Expression*>* args = expr->arguments();
1344  VisitForValues(args);
1345 
1346  // Create node to perform the runtime call.
1347  Runtime::FunctionId functionId = function->function_id;
1348  const Operator* call = javascript()->Runtime(functionId, args->length());
1349  Node* value = ProcessArguments(call, args->length());
1350  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1351  ast_context()->ProduceValue(value);
1352 }
1353 
1354 
1355 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1356  switch (expr->op()) {
1357  case Token::DELETE:
1358  return VisitDelete(expr);
1359  case Token::VOID:
1360  return VisitVoid(expr);
1361  case Token::TYPEOF:
1362  return VisitTypeof(expr);
1363  case Token::NOT:
1364  return VisitNot(expr);
1365  default:
1366  UNREACHABLE();
1367  }
1368 }
1369 
1370 
1371 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
1372  DCHECK(expr->expression()->IsValidReferenceExpression());
1373 
1374  // Left-hand side can only be a property, a global or a variable slot.
1375  Property* property = expr->expression()->AsProperty();
1376  LhsKind assign_type = DetermineLhsKind(expr->expression());
1377 
1378  // Reserve space for result of postfix operation.
1379  bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
1380  if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());
1381 
1382  // Evaluate LHS expression and get old value.
1383  Node* old_value = NULL;
1384  int stack_depth = -1;
1385  switch (assign_type) {
1386  case VARIABLE: {
1387  Variable* variable = expr->expression()->AsVariableProxy()->var();
1388  old_value = BuildVariableLoad(variable, expr->expression()->id());
1389  stack_depth = 0;
1390  break;
1391  }
1392  case NAMED_PROPERTY: {
1393  VisitForValue(property->obj());
1394  Node* object = environment()->Top();
1395  Unique<Name> name =
1396  MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1397  old_value = NewNode(javascript()->LoadNamed(name), object);
1398  PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1399  stack_depth = 1;
1400  break;
1401  }
1402  case KEYED_PROPERTY: {
1403  VisitForValue(property->obj());
1404  VisitForValue(property->key());
1405  Node* key = environment()->Top();
1406  Node* object = environment()->Peek(1);
1407  old_value = NewNode(javascript()->LoadProperty(), object, key);
1408  PrepareFrameState(old_value, property->LoadId(), kPushOutput);
1409  stack_depth = 2;
1410  break;
1411  }
1412  }
1413 
1414  // Convert old value into a number.
1415  old_value = NewNode(javascript()->ToNumber(), old_value);
1416 
1417  // Save result for postfix expressions at correct stack depth.
1418  if (is_postfix) environment()->Poke(stack_depth, old_value);
1419 
1420  // Create node to perform +1/-1 operation.
1421  Node* value =
1422  BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
1423  // TODO(jarin) Insert proper bailout id here (will need to change
1424  // full code generator).
1426 
1427  // Store the value.
1428  switch (assign_type) {
1429  case VARIABLE: {
1430  Variable* variable = expr->expression()->AsVariableProxy()->var();
1431  environment()->Push(value);
1432  BuildVariableAssignment(variable, value, expr->op(),
1433  expr->AssignmentId());
1434  environment()->Pop();
1435  break;
1436  }
1437  case NAMED_PROPERTY: {
1438  Node* object = environment()->Pop();
1439  Unique<Name> name =
1440  MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1441  Node* store =
1442  NewNode(javascript()->StoreNamed(strict_mode(), name), object, value);
1443  environment()->Push(value);
1444  PrepareFrameState(store, expr->AssignmentId());
1445  environment()->Pop();
1446  break;
1447  }
1448  case KEYED_PROPERTY: {
1449  Node* key = environment()->Pop();
1450  Node* object = environment()->Pop();
1451  Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object,
1452  key, value);
1453  environment()->Push(value);
1454  PrepareFrameState(store, expr->AssignmentId());
1455  environment()->Pop();
1456  break;
1457  }
1458  }
1459 
1460  // Restore old value for postfix expressions.
1461  if (is_postfix) value = environment()->Pop();
1462 
1463  ast_context()->ProduceValue(value);
1464 }
1465 
1466 
1467 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1468  switch (expr->op()) {
1469  case Token::COMMA:
1470  return VisitComma(expr);
1471  case Token::OR:
1472  case Token::AND:
1473  return VisitLogicalExpression(expr);
1474  default: {
1475  VisitForValue(expr->left());
1476  VisitForValue(expr->right());
1477  Node* right = environment()->Pop();
1478  Node* left = environment()->Pop();
1479  Node* value = BuildBinaryOp(left, right, expr->op());
1480  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1481  ast_context()->ProduceValue(value);
1482  }
1483  }
1484 }
1485 
1486 
1487 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
1488  const Operator* op;
1489  switch (expr->op()) {
1490  case Token::EQ:
1491  op = javascript()->Equal();
1492  break;
1493  case Token::NE:
1494  op = javascript()->NotEqual();
1495  break;
1496  case Token::EQ_STRICT:
1497  op = javascript()->StrictEqual();
1498  break;
1499  case Token::NE_STRICT:
1500  op = javascript()->StrictNotEqual();
1501  break;
1502  case Token::LT:
1503  op = javascript()->LessThan();
1504  break;
1505  case Token::GT:
1506  op = javascript()->GreaterThan();
1507  break;
1508  case Token::LTE:
1509  op = javascript()->LessThanOrEqual();
1510  break;
1511  case Token::GTE:
1512  op = javascript()->GreaterThanOrEqual();
1513  break;
1514  case Token::INSTANCEOF:
1515  op = javascript()->InstanceOf();
1516  break;
1517  case Token::IN:
1518  op = javascript()->HasProperty();
1519  break;
1520  default:
1521  op = NULL;
1522  UNREACHABLE();
1523  }
1524  VisitForValue(expr->left());
1525  VisitForValue(expr->right());
1526  Node* right = environment()->Pop();
1527  Node* left = environment()->Pop();
1528  Node* value = NewNode(op, left, right);
1529  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1530  ast_context()->ProduceValue(value);
1531 }
1532 
1533 
1534 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
1535  Node* value = GetFunctionClosure();
1536  ast_context()->ProduceValue(value);
1537 }
1538 
1539 
1540 void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
1541  UNREACHABLE();
1542 }
1543 
1544 
1545 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
1546 
1547 
1549  DCHECK(globals()->is_empty());
1550  AstVisitor::VisitDeclarations(declarations);
1551  if (globals()->is_empty()) return;
1552  Handle<FixedArray> data =
1553  isolate()->factory()->NewFixedArray(globals()->length(), TENURED);
1554  for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i));
1555  int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
1556  DeclareGlobalsNativeFlag::encode(info()->is_native()) |
1558  Node* flags = jsgraph()->Constant(encoded_flags);
1559  Node* pairs = jsgraph()->Constant(data);
1560  const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3);
1562  globals()->Rewind(0);
1563 }
1564 
1565 
1567  if (stmt == NULL) return;
1568  Visit(stmt);
1569 }
1570 
1571 
1573  LoopBuilder* loop, int drop_extra) {
1574  BreakableScope scope(this, stmt, loop, drop_extra);
1575  Visit(stmt->body());
1576 }
1577 
1578 
1579 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
1580  Node* value;
1581  if (expr->expression()->IsVariableProxy()) {
1582  // Delete of an unqualified identifier is only allowed in classic mode but
1583  // deleting "this" is allowed in all language modes.
1584  Variable* variable = expr->expression()->AsVariableProxy()->var();
1585  DCHECK(strict_mode() == SLOPPY || variable->is_this());
1586  value = BuildVariableDelete(variable);
1587  } else if (expr->expression()->IsProperty()) {
1588  Property* property = expr->expression()->AsProperty();
1589  VisitForValue(property->obj());
1590  VisitForValue(property->key());
1591  Node* key = environment()->Pop();
1592  Node* object = environment()->Pop();
1593  value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
1594  } else {
1595  VisitForEffect(expr->expression());
1596  value = jsgraph()->TrueConstant();
1597  }
1598  ast_context()->ProduceValue(value);
1599 }
1600 
1601 
1602 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
1603  VisitForEffect(expr->expression());
1604  Node* value = jsgraph()->UndefinedConstant();
1605  ast_context()->ProduceValue(value);
1606 }
1607 
1608 
1609 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
1610  Node* operand;
1611  if (expr->expression()->IsVariableProxy()) {
1612  // Typeof does not throw a reference error on global variables, hence we
1613  // perform a non-contextual load in case the operand is a variable proxy.
1614  Variable* variable = expr->expression()->AsVariableProxy()->var();
1615  operand =
1616  BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
1617  } else {
1618  VisitForValue(expr->expression());
1619  operand = environment()->Pop();
1620  }
1621  Node* value = NewNode(javascript()->TypeOf(), operand);
1622  ast_context()->ProduceValue(value);
1623 }
1624 
1625 
1626 void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
1627  VisitForValue(expr->expression());
1628  Node* operand = environment()->Pop();
1629  // TODO(mstarzinger): Possible optimization when we are in effect context.
1630  Node* value = NewNode(javascript()->UnaryNot(), operand);
1631  ast_context()->ProduceValue(value);
1632 }
1633 
1634 
1635 void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
1636  VisitForEffect(expr->left());
1637  Visit(expr->right());
1638  ast_context()->ReplaceValue();
1639 }
1640 
1641 
1642 void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
1643  bool is_logical_and = expr->op() == Token::AND;
1644  IfBuilder compare_if(this);
1645  VisitForValue(expr->left());
1646  Node* condition = environment()->Top();
1647  compare_if.If(BuildToBoolean(condition));
1648  compare_if.Then();
1649  if (is_logical_and) {
1650  environment()->Pop();
1651  Visit(expr->right());
1652  } else if (ast_context()->IsEffect()) {
1653  environment()->Pop();
1654  }
1655  compare_if.Else();
1656  if (!is_logical_and) {
1657  environment()->Pop();
1658  Visit(expr->right());
1659  } else if (ast_context()->IsEffect()) {
1660  environment()->Pop();
1661  }
1662  compare_if.End();
1663  ast_context()->ReplaceValue();
1664 }
1665 
1666 
1667 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
1668  DCHECK(environment()->stack_height() >= arity);
1669  Node** all = info()->zone()->NewArray<Node*>(arity);
1670  for (int i = arity - 1; i >= 0; --i) {
1671  all[i] = environment()->Pop();
1672  }
1673  Node* value = NewNode(op, arity, all);
1674  return value;
1675 }
1676 
1677 
1678 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
1679  int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
1680  if (heap_slots <= 0) return context;
1681  set_current_context(context);
1682 
1683  // Allocate a new local context.
1684  const Operator* op = javascript()->CreateFunctionContext();
1685  Node* local_context = NewNode(op, closure);
1686  set_current_context(local_context);
1687 
1688  // Copy parameters into context if necessary.
1689  int num_parameters = info()->scope()->num_parameters();
1690  for (int i = 0; i < num_parameters; i++) {
1691  Variable* variable = info()->scope()->parameter(i);
1692  if (!variable->IsContextSlot()) continue;
1693  // Temporary parameter node. The parameter indices are shifted by 1
1694  // (receiver is parameter index -1 but environment index 0).
1695  Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start());
1696  // Context variable (at bottom of the context chain).
1697  DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope()));
1698  const Operator* op = javascript()->StoreContext(0, variable->index());
1699  NewNode(op, local_context, parameter);
1700  }
1701 
1702  return local_context;
1703 }
1704 
1705 
1707  if (arguments == NULL) return NULL;
1708 
1709  // Allocate and initialize a new arguments object.
1710  Node* callee = GetFunctionClosure();
1711  const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1);
1712  Node* object = NewNode(op, callee);
1713 
1714  // Assign the object to the arguments variable.
1715  DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
1716  // This should never lazy deopt, so it is fine to send invalid bailout id.
1717  BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
1718 
1719  return object;
1720 }
1721 
1722 
1723 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
1724  Node* not_hole) {
1725  IfBuilder hole_check(this);
1726  Node* the_hole = jsgraph()->TheHoleConstant();
1727  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1728  hole_check.If(check);
1729  hole_check.Then();
1730  environment()->Push(for_hole);
1731  hole_check.Else();
1732  environment()->Push(not_hole);
1733  hole_check.End();
1734  return environment()->Pop();
1735 }
1736 
1737 
1738 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
1739  Node* not_hole) {
1740  IfBuilder hole_check(this);
1741  Node* the_hole = jsgraph()->TheHoleConstant();
1742  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
1743  hole_check.If(check);
1744  hole_check.Then();
1746  hole_check.Else();
1747  environment()->Push(not_hole);
1748  hole_check.End();
1749  return environment()->Pop();
1750 }
1751 
1752 
1754  BailoutId bailout_id,
1755  ContextualMode contextual_mode) {
1756  Node* the_hole = jsgraph()->TheHoleConstant();
1757  VariableMode mode = variable->mode();
1758  switch (variable->location()) {
1759  case Variable::UNALLOCATED: {
1760  // Global var, const, or let variable.
1761  Node* global = BuildLoadGlobalObject();
1762  Unique<Name> name = MakeUnique(variable->name());
1763  const Operator* op = javascript()->LoadNamed(name, contextual_mode);
1764  Node* node = NewNode(op, global);
1765  PrepareFrameState(node, bailout_id, kPushOutput);
1766  return node;
1767  }
1768  case Variable::PARAMETER:
1769  case Variable::LOCAL: {
1770  // Local var, const, or let variable.
1771  Node* value = environment()->Lookup(variable);
1772  if (mode == CONST_LEGACY) {
1773  // Perform check for uninitialized legacy const variables.
1774  if (value->op() == the_hole->op()) {
1775  value = jsgraph()->UndefinedConstant();
1776  } else if (value->opcode() == IrOpcode::kPhi) {
1777  Node* undefined = jsgraph()->UndefinedConstant();
1778  value = BuildHoleCheckSilent(value, undefined, value);
1779  }
1780  } else if (mode == LET || mode == CONST) {
1781  // Perform check for uninitialized let/const variables.
1782  if (value->op() == the_hole->op()) {
1783  value = BuildThrowReferenceError(variable);
1784  } else if (value->opcode() == IrOpcode::kPhi) {
1785  value = BuildHoleCheckThrow(value, variable, value);
1786  }
1787  }
1788  return value;
1789  }
1790  case Variable::CONTEXT: {
1791  // Context variable (potentially up the context chain).
1792  int depth = current_scope()->ContextChainLength(variable->scope());
1793  bool immutable = variable->maybe_assigned() == kNotAssigned;
1794  const Operator* op =
1795  javascript()->LoadContext(depth, variable->index(), immutable);
1796  Node* value = NewNode(op, current_context());
1797  // TODO(titzer): initialization checks are redundant for already
1798  // initialized immutable context loads, but only specialization knows.
1799  // Maybe specializer should be a parameter to the graph builder?
1800  if (mode == CONST_LEGACY) {
1801  // Perform check for uninitialized legacy const variables.
1802  Node* undefined = jsgraph()->UndefinedConstant();
1803  value = BuildHoleCheckSilent(value, undefined, value);
1804  } else if (mode == LET || mode == CONST) {
1805  // Perform check for uninitialized let/const variables.
1806  value = BuildHoleCheckThrow(value, variable, value);
1807  }
1808  return value;
1809  }
1810  case Variable::LOOKUP: {
1811  // Dynamic lookup of context variable (anywhere in the chain).
1812  Node* name = jsgraph()->Constant(variable->name());
1813  Runtime::FunctionId function_id =
1814  (contextual_mode == CONTEXTUAL)
1815  ? Runtime::kLoadLookupSlot
1816  : Runtime::kLoadLookupSlotNoReferenceError;
1817  const Operator* op = javascript()->Runtime(function_id, 2);
1818  Node* pair = NewNode(op, current_context(), name);
1819  return NewNode(common()->Projection(0), pair);
1820  }
1821  }
1822  UNREACHABLE();
1823  return NULL;
1824 }
1825 
1826 
1828  switch (variable->location()) {
1829  case Variable::UNALLOCATED: {
1830  // Global var, const, or let variable.
1831  Node* global = BuildLoadGlobalObject();
1832  Node* name = jsgraph()->Constant(variable->name());
1833  const Operator* op = javascript()->DeleteProperty(strict_mode());
1834  return NewNode(op, global, name);
1835  }
1836  case Variable::PARAMETER:
1837  case Variable::LOCAL:
1838  case Variable::CONTEXT:
1839  // Local var, const, or let variable or context variable.
1840  return variable->is_this() ? jsgraph()->TrueConstant()
1841  : jsgraph()->FalseConstant();
1842  case Variable::LOOKUP: {
1843  // Dynamic lookup of context variable (anywhere in the chain).
1844  Node* name = jsgraph()->Constant(variable->name());
1845  const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2);
1846  return NewNode(op, current_context(), name);
1847  }
1848  }
1849  UNREACHABLE();
1850  return NULL;
1851 }
1852 
1853 
1855  Token::Value op,
1856  BailoutId bailout_id) {
1857  Node* the_hole = jsgraph()->TheHoleConstant();
1858  VariableMode mode = variable->mode();
1859  switch (variable->location()) {
1860  case Variable::UNALLOCATED: {
1861  // Global var, const, or let variable.
1862  Node* global = BuildLoadGlobalObject();
1863  Unique<Name> name = MakeUnique(variable->name());
1864  const Operator* op = javascript()->StoreNamed(strict_mode(), name);
1865  Node* store = NewNode(op, global, value);
1866  PrepareFrameState(store, bailout_id);
1867  return store;
1868  }
1869  case Variable::PARAMETER:
1870  case Variable::LOCAL:
1871  // Local var, const, or let variable.
1872  if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
1873  // Perform an initialization check for legacy const variables.
1874  Node* current = environment()->Lookup(variable);
1875  if (current->op() != the_hole->op()) {
1876  value = BuildHoleCheckSilent(current, value, current);
1877  }
1878  } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
1879  // Non-initializing assignments to legacy const is ignored.
1880  return value;
1881  } else if (mode == LET && op != Token::INIT_LET) {
1882  // Perform an initialization check for let declared variables.
1883  // Also note that the dynamic hole-check is only done to ensure that
1884  // this does not break in the presence of do-expressions within the
1885  // temporal dead zone of a let declared variable.
1886  Node* current = environment()->Lookup(variable);
1887  if (current->op() == the_hole->op()) {
1888  value = BuildThrowReferenceError(variable);
1889  } else if (value->opcode() == IrOpcode::kPhi) {
1890  value = BuildHoleCheckThrow(current, variable, value);
1891  }
1892  } else if (mode == CONST && op != Token::INIT_CONST) {
1893  // All assignments to const variables are early errors.
1894  UNREACHABLE();
1895  }
1896  environment()->Bind(variable, value);
1897  return value;
1898  case Variable::CONTEXT: {
1899  // Context variable (potentially up the context chain).
1900  int depth = current_scope()->ContextChainLength(variable->scope());
1901  if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
1902  // Perform an initialization check for legacy const variables.
1903  const Operator* op =
1904  javascript()->LoadContext(depth, variable->index(), false);
1905  Node* current = NewNode(op, current_context());
1906  value = BuildHoleCheckSilent(current, value, current);
1907  } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
1908  // Non-initializing assignments to legacy const is ignored.
1909  return value;
1910  } else if (mode == LET && op != Token::INIT_LET) {
1911  // Perform an initialization check for let declared variables.
1912  const Operator* op =
1913  javascript()->LoadContext(depth, variable->index(), false);
1914  Node* current = NewNode(op, current_context());
1915  value = BuildHoleCheckThrow(current, variable, value);
1916  } else if (mode == CONST && op != Token::INIT_CONST) {
1917  // All assignments to const variables are early errors.
1918  UNREACHABLE();
1919  }
1920  const Operator* op = javascript()->StoreContext(depth, variable->index());
1921  return NewNode(op, current_context(), value);
1922  }
1923  case Variable::LOOKUP: {
1924  // Dynamic lookup of context variable (anywhere in the chain).
1925  Node* name = jsgraph()->Constant(variable->name());
1926  Node* strict = jsgraph()->Constant(strict_mode());
1927  // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
1928  // initializations of const declarations.
1929  const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4);
1930  return NewNode(op, value, current_context(), name, strict);
1931  }
1932  }
1933  UNREACHABLE();
1934  return NULL;
1935 }
1936 
1937 
1938 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
1939  // TODO(sigurds) Use simplified load here once it is ready.
1940  Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
1941  jsgraph()->Int32Constant(offset - kHeapObjectTag));
1942  return field_load;
1943 }
1944 
1945 
1947  Node* global = BuildLoadGlobalObject();
1948  Node* builtins =
1950  return builtins;
1951 }
1952 
1953 
1955  Node* context = GetFunctionContext();
1956  const Operator* load_op =
1958  return NewNode(load_op, context);
1959 }
1960 
1961 
1963  // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
1964  return NewNode(javascript()->ToBoolean(), value);
1965 }
1966 
1967 
1969  // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
1970  Node* variable_name = jsgraph()->Constant(variable->name());
1971  const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1);
1972  return NewNode(op, variable_name);
1973 }
1974 
1975 
1976 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
1977  const Operator* js_op;
1978  switch (op) {
1979  case Token::BIT_OR:
1980  js_op = javascript()->BitwiseOr();
1981  break;
1982  case Token::BIT_AND:
1983  js_op = javascript()->BitwiseAnd();
1984  break;
1985  case Token::BIT_XOR:
1986  js_op = javascript()->BitwiseXor();
1987  break;
1988  case Token::SHL:
1989  js_op = javascript()->ShiftLeft();
1990  break;
1991  case Token::SAR:
1992  js_op = javascript()->ShiftRight();
1993  break;
1994  case Token::SHR:
1995  js_op = javascript()->ShiftRightLogical();
1996  break;
1997  case Token::ADD:
1998  js_op = javascript()->Add();
1999  break;
2000  case Token::SUB:
2001  js_op = javascript()->Subtract();
2002  break;
2003  case Token::MUL:
2004  js_op = javascript()->Multiply();
2005  break;
2006  case Token::DIV:
2007  js_op = javascript()->Divide();
2008  break;
2009  case Token::MOD:
2010  js_op = javascript()->Modulus();
2011  break;
2012  default:
2013  UNREACHABLE();
2014  js_op = NULL;
2015  }
2016  return NewNode(js_op, left, right);
2017 }
2018 
2019 
2021  OutputFrameStateCombine combine) {
2022  if (OperatorProperties::HasFrameStateInput(node->op())) {
2023  DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() ==
2024  IrOpcode::kDead);
2026  node, environment()->Checkpoint(ast_id, combine));
2027  }
2028 }
2029 
2030 }
2031 }
2032 } // namespace v8::internal::compiler
bool IsEffect() const
Definition: hydrogen.h:763
virtual void Accept(AstVisitor *v)=0
static BailoutId FunctionEntry()
Definition: utils.h:961
static BailoutId None()
Definition: utils.h:960
static U encode(T value)
Definition: utils.h:217
static bool IsCompileTimeValue(Expression *expression)
Definition: parser.cc:3331
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script, CompilationInfo *outer)
Definition: compiler.cc:1243
virtual bool IsValidReferenceExpression() const
Definition: ast.h:325
static const int kBuiltinsOffset
Definition: objects.h:7458
Factory * factory()
Definition: isolate.h:982
Statement * body() const
Definition: ast.h:732
static int OffsetOfFunctionWithId(Builtins::JavaScript id)
Definition: objects.h:7520
static const int kLiteralsOffset
Definition: objects.h:7382
T & at(int i) const
Definition: list.h:69
Mode rmode() const
Definition: assembler.h:459
int num_parameters() const
Definition: scopes.h:321
VariableDeclaration * function() const
Definition: scopes.h:309
int ContextChainLength(Scope *scope)
Definition: scopes.cc:715
bool is_function_scope() const
Definition: scopes.h:265
ZoneList< Declaration * > * declarations()
Definition: scopes.h:327
Variable * arguments() const
Definition: scopes.h:324
Variable * parameter(int index) const
Definition: scopes.h:316
void set(T *value)
Definition: utils.h:417
Handle< String > name() const
Definition: variables.h:71
bool binding_needs_init() const
Definition: variables.h:103
VariableMode mode() const
Definition: variables.h:73
bool IsStackAllocated() const
Definition: variables.h:96
Location location() const
Definition: variables.h:124
MaybeAssignedFlag maybe_assigned() const
Definition: variables.h:83
bool is_this() const
Definition: variables.h:107
Scope * scope() const
Definition: variables.h:69
bool IsContextSlot() const
Definition: variables.h:97
T * NewArray(int length)
Definition: zone.h:46
Node * Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine)
Environment(AstGraphBuilder *builder, Scope *scope, Node *control_dependency)
void UpdateStateValues(Node **state_values, int offset, int count)
Node * BuildHoleCheckSilent(Node *value, Node *for_hole, Node *not_hole)
void VisitForInAssignment(Expression *expr, Node *value)
Node * BuildVariableLoad(Variable *var, BailoutId bailout_id, ContextualMode mode=CONTEXTUAL)
Node * BuildArgumentsObject(Variable *arguments)
virtual BaseEnvironment * CopyEnvironment(BaseEnvironment *env)
void VisitIterationBody(IterationStatement *stmt, LoopBuilder *loop, int)
virtual void VisitDeclarations(ZoneList< Declaration * > *declarations)
Node * BuildHoleCheckThrow(Node *value, Variable *var, Node *not_hole)
Node * ProcessArguments(const Operator *op, int arity)
void VisitForValues(ZoneList< Expression * > *exprs)
Node * BuildLoadObjectField(Node *object, int offset)
Node * BuildLocalFunctionContext(Node *context, Node *closure)
AstGraphBuilder(CompilationInfo *info, JSGraph *jsgraph)
void PrepareFrameState(Node *node, BailoutId ast_id, OutputFrameStateCombine combine=kIgnoreOutput)
void VisitLogicalExpression(BinaryOperation *expr)
ZoneList< Handle< Object > > * globals()
Node * BuildVariableAssignment(Variable *var, Node *value, Token::Value op, BailoutId bailout_id)
Node * BuildBinaryOp(Node *left, Node *right, Token::Value op)
Node * NewNode(const Operator *op)
Definition: graph-builder.h:27
Node * NewNode(const Operator *op, int input_count, Node **inputs)
Definition: graph.cc:24
Node * Constant(Handle< Object > value)
Definition: js-graph.cc:115
const Operator * LoadNamed(Unique< Name > name, ContextualMode contextual_mode=NOT_CONTEXTUAL)
Definition: js-operator.h:127
const Operator * Runtime(Runtime::FunctionId function, int arguments)
Definition: js-operator.h:183
const Operator * LoadContext(uint16_t depth, uint32_t index, bool immutable)
Definition: js-operator.h:152
const Operator * CallNew(int arguments)
Definition: js-operator.h:120
const Operator * StoreContext(uint16_t depth, uint32_t index)
Definition: js-operator.h:157
const Operator * DeleteProperty(StrictMode strict_mode)
Definition: js-operator.h:145
const Operator * Call(int arguments, CallFunctionFlags flags)
Definition: js-operator.h:114
const Operator * StoreNamed(StrictMode strict_mode, Unique< Name > name)
Definition: js-operator.h:139
static Node * GetFrameStateInput(Node *node)
static void ReplaceFrameStateInput(Node *node, Node *frame_state)
static bool HasFrameStateInput(const Operator *op)
Unique< T > MakeUnique(Handle< T > object)
CommonOperatorBuilder * common() const
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_BOOL(enable_unaligned_accesses
#define COMMA
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define UNIMPLEMENTED()
Definition: logging.h:28
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
MachineType TypeOf(MachineType machine_type)
Definition: machine-type.h:70
static LhsKind DetermineLhsKind(Expression *expr)
static Handle< SharedFunctionInfo > SearchSharedFunctionInfo(Code *unoptimized_code, FunctionLiteral *expr)
int ToNumber(Register reg)
@ kNotAssigned
Definition: globals.h:757
@ CONST_LEGACY
Definition: globals.h:671
@ NOT_CONTEXTUAL
Definition: objects.h:174
const int kHeapObjectTag
Definition: v8.h:5737
@ NO_CALL_FUNCTION_FLAGS
Definition: globals.h:469
@ CALL_AS_METHOD
Definition: globals.h:470
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static Handle< Value > Throw(Isolate *isolate, const char *message)
Definition: d8.cc:72
#define VOID
#define IN
@ NONE