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

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

Powered by Google App Engine
This is Rietveld 408576698