Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: src/compiler/ast-graph-builder.cc

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

Powered by Google App Engine
This is Rietveld 408576698