OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/compiler/control-builders.h" | 8 #include "src/compiler/control-builders.h" |
9 #include "src/compiler/machine-operator.h" | 9 #include "src/compiler/machine-operator.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 globals_(0, info->zone()), | 24 globals_(0, info->zone()), |
25 breakable_(NULL), | 25 breakable_(NULL), |
26 execution_context_(NULL) { | 26 execution_context_(NULL) { |
27 InitializeAstVisitor(info->zone()); | 27 InitializeAstVisitor(info->zone()); |
28 } | 28 } |
29 | 29 |
30 | 30 |
31 Node* AstGraphBuilder::GetFunctionClosure() { | 31 Node* AstGraphBuilder::GetFunctionClosure() { |
32 if (!function_closure_.is_set()) { | 32 if (!function_closure_.is_set()) { |
33 // Parameter -1 is special for the function closure | 33 // Parameter -1 is special for the function closure |
34 Operator* op = common()->Parameter(-1); | 34 const Operator* op = common()->Parameter(-1); |
35 Node* node = NewNode(op, graph()->start()); | 35 Node* node = NewNode(op, graph()->start()); |
36 function_closure_.set(node); | 36 function_closure_.set(node); |
37 } | 37 } |
38 return function_closure_.get(); | 38 return function_closure_.get(); |
39 } | 39 } |
40 | 40 |
41 | 41 |
42 Node* AstGraphBuilder::GetFunctionContext() { | 42 Node* AstGraphBuilder::GetFunctionContext() { |
43 if (!function_context_.is_set()) { | 43 if (!function_context_.is_set()) { |
44 // Parameter (arity + 1) is special for the outer context of the function | 44 // Parameter (arity + 1) is special for the outer context of the function |
45 Operator* op = common()->Parameter(info()->num_parameters() + 1); | 45 const Operator* op = common()->Parameter(info()->num_parameters() + 1); |
46 Node* node = NewNode(op, graph()->start()); | 46 Node* node = NewNode(op, graph()->start()); |
47 function_context_.set(node); | 47 function_context_.set(node); |
48 } | 48 } |
49 return function_context_.get(); | 49 return function_context_.get(); |
50 } | 50 } |
51 | 51 |
52 | 52 |
53 bool AstGraphBuilder::CreateGraph() { | 53 bool AstGraphBuilder::CreateGraph() { |
54 Scope* scope = info()->scope(); | 54 Scope* scope = info()->scope(); |
55 DCHECK(graph() != NULL); | 55 DCHECK(graph() != NULL); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } else { | 204 } else { |
205 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); | 205 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); |
206 for (int i = 0; i < count; i++) { | 206 for (int i = 0; i < count; i++) { |
207 if ((*state_values)->InputAt(i) != env_values[i]) { | 207 if ((*state_values)->InputAt(i) != env_values[i]) { |
208 should_update = true; | 208 should_update = true; |
209 break; | 209 break; |
210 } | 210 } |
211 } | 211 } |
212 } | 212 } |
213 if (should_update) { | 213 if (should_update) { |
214 Operator* op = common()->StateValues(count); | 214 const Operator* op = common()->StateValues(count); |
215 (*state_values) = graph()->NewNode(op, count, env_values); | 215 (*state_values) = graph()->NewNode(op, count, env_values); |
216 } | 216 } |
217 } | 217 } |
218 | 218 |
219 | 219 |
220 Node* AstGraphBuilder::Environment::Checkpoint( | 220 Node* AstGraphBuilder::Environment::Checkpoint( |
221 BailoutId ast_id, OutputFrameStateCombine combine) { | 221 BailoutId ast_id, OutputFrameStateCombine combine) { |
222 UpdateStateValues(¶meters_node_, 0, parameters_count()); | 222 UpdateStateValues(¶meters_node_, 0, parameters_count()); |
223 UpdateStateValues(&locals_node_, parameters_count(), locals_count()); | 223 UpdateStateValues(&locals_node_, parameters_count(), locals_count()); |
224 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), | 224 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), |
225 stack_height()); | 225 stack_height()); |
226 | 226 |
227 Operator* op = common()->FrameState(ast_id, combine); | 227 const Operator* op = common()->FrameState(ast_id, combine); |
228 | 228 |
229 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, | 229 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, |
230 GetContext(), | 230 GetContext(), |
231 builder()->jsgraph()->UndefinedConstant()); | 231 builder()->jsgraph()->UndefinedConstant()); |
232 } | 232 } |
233 | 233 |
234 | 234 |
235 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, | 235 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, |
236 Expression::Context kind) | 236 Expression::Context kind) |
237 : kind_(kind), owner_(own), outer_(own->ast_context()) { | 237 : kind_(kind), owner_(own), outer_(own->ast_context()) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 case Variable::PARAMETER: | 367 case Variable::PARAMETER: |
368 case Variable::LOCAL: | 368 case Variable::LOCAL: |
369 if (hole_init) { | 369 if (hole_init) { |
370 Node* value = jsgraph()->TheHoleConstant(); | 370 Node* value = jsgraph()->TheHoleConstant(); |
371 environment()->Bind(variable, value); | 371 environment()->Bind(variable, value); |
372 } | 372 } |
373 break; | 373 break; |
374 case Variable::CONTEXT: | 374 case Variable::CONTEXT: |
375 if (hole_init) { | 375 if (hole_init) { |
376 Node* value = jsgraph()->TheHoleConstant(); | 376 Node* value = jsgraph()->TheHoleConstant(); |
377 Operator* op = javascript()->StoreContext(0, variable->index()); | 377 const Operator* op = javascript()->StoreContext(0, variable->index()); |
378 NewNode(op, current_context(), value); | 378 NewNode(op, current_context(), value); |
379 } | 379 } |
380 break; | 380 break; |
381 case Variable::LOOKUP: | 381 case Variable::LOOKUP: |
382 UNIMPLEMENTED(); | 382 UNIMPLEMENTED(); |
383 } | 383 } |
384 } | 384 } |
385 | 385 |
386 | 386 |
387 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 387 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
(...skipping 11 matching lines...) Expand all Loading... |
399 case Variable::PARAMETER: | 399 case Variable::PARAMETER: |
400 case Variable::LOCAL: { | 400 case Variable::LOCAL: { |
401 VisitForValue(decl->fun()); | 401 VisitForValue(decl->fun()); |
402 Node* value = environment()->Pop(); | 402 Node* value = environment()->Pop(); |
403 environment()->Bind(variable, value); | 403 environment()->Bind(variable, value); |
404 break; | 404 break; |
405 } | 405 } |
406 case Variable::CONTEXT: { | 406 case Variable::CONTEXT: { |
407 VisitForValue(decl->fun()); | 407 VisitForValue(decl->fun()); |
408 Node* value = environment()->Pop(); | 408 Node* value = environment()->Pop(); |
409 Operator* op = javascript()->StoreContext(0, variable->index()); | 409 const Operator* op = javascript()->StoreContext(0, variable->index()); |
410 NewNode(op, current_context(), value); | 410 NewNode(op, current_context(), value); |
411 break; | 411 break; |
412 } | 412 } |
413 case Variable::LOOKUP: | 413 case Variable::LOOKUP: |
414 UNIMPLEMENTED(); | 414 UNIMPLEMENTED(); |
415 } | 415 } |
416 } | 416 } |
417 | 417 |
418 | 418 |
419 void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) { | 419 void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) { |
(...skipping 26 matching lines...) Expand all Loading... |
446 | 446 |
447 | 447 |
448 void AstGraphBuilder::VisitBlock(Block* stmt) { | 448 void AstGraphBuilder::VisitBlock(Block* stmt) { |
449 BlockBuilder block(this); | 449 BlockBuilder block(this); |
450 BreakableScope scope(this, stmt, &block, 0); | 450 BreakableScope scope(this, stmt, &block, 0); |
451 if (stmt->labels() != NULL) block.BeginBlock(); | 451 if (stmt->labels() != NULL) block.BeginBlock(); |
452 if (stmt->scope() == NULL) { | 452 if (stmt->scope() == NULL) { |
453 // Visit statements in the same scope, no declarations. | 453 // Visit statements in the same scope, no declarations. |
454 VisitStatements(stmt->statements()); | 454 VisitStatements(stmt->statements()); |
455 } else { | 455 } else { |
456 Operator* op = javascript()->CreateBlockContext(); | 456 const Operator* op = javascript()->CreateBlockContext(); |
457 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo()); | 457 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo()); |
458 Node* context = NewNode(op, scope_info, GetFunctionClosure()); | 458 Node* context = NewNode(op, scope_info, GetFunctionClosure()); |
459 ContextScope scope(this, stmt->scope(), context); | 459 ContextScope scope(this, stmt->scope(), context); |
460 | 460 |
461 // Visit declarations and statements in a block scope. | 461 // Visit declarations and statements in a block scope. |
462 VisitDeclarations(stmt->scope()->declarations()); | 462 VisitDeclarations(stmt->scope()->declarations()); |
463 VisitStatements(stmt->statements()); | 463 VisitStatements(stmt->statements()); |
464 } | 464 } |
465 if (stmt->labels() != NULL) block.EndBlock(); | 465 if (stmt->labels() != NULL) block.EndBlock(); |
466 } | 466 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 VisitForValue(stmt->expression()); | 512 VisitForValue(stmt->expression()); |
513 Node* result = environment()->Pop(); | 513 Node* result = environment()->Pop(); |
514 Node* control = NewNode(common()->Return(), result); | 514 Node* control = NewNode(common()->Return(), result); |
515 UpdateControlDependencyToLeaveFunction(control); | 515 UpdateControlDependencyToLeaveFunction(control); |
516 } | 516 } |
517 | 517 |
518 | 518 |
519 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 519 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
520 VisitForValue(stmt->expression()); | 520 VisitForValue(stmt->expression()); |
521 Node* value = environment()->Pop(); | 521 Node* value = environment()->Pop(); |
522 Operator* op = javascript()->CreateWithContext(); | 522 const Operator* op = javascript()->CreateWithContext(); |
523 Node* context = NewNode(op, value, GetFunctionClosure()); | 523 Node* context = NewNode(op, value, GetFunctionClosure()); |
524 ContextScope scope(this, stmt->scope(), context); | 524 ContextScope scope(this, stmt->scope(), context); |
525 Visit(stmt->statement()); | 525 Visit(stmt->statement()); |
526 } | 526 } |
527 | 527 |
528 | 528 |
529 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 529 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
530 ZoneList<CaseClause*>* clauses = stmt->cases(); | 530 ZoneList<CaseClause*>* clauses = stmt->cases(); |
531 SwitchBuilder compare_switch(this, clauses->length()); | 531 SwitchBuilder compare_switch(this, clauses->length()); |
532 BreakableScope scope(this, stmt, &compare_switch, 0); | 532 BreakableScope scope(this, stmt, &compare_switch, 0); |
(...skipping 11 matching lines...) Expand all Loading... |
544 // The default is not a test, remember index. | 544 // The default is not a test, remember index. |
545 if (clause->is_default()) { | 545 if (clause->is_default()) { |
546 default_index = i; | 546 default_index = i; |
547 continue; | 547 continue; |
548 } | 548 } |
549 | 549 |
550 // Create nodes to perform label comparison as if via '==='. The switch | 550 // Create nodes to perform label comparison as if via '==='. The switch |
551 // value is still on the operand stack while the label is evaluated. | 551 // value is still on the operand stack while the label is evaluated. |
552 VisitForValue(clause->label()); | 552 VisitForValue(clause->label()); |
553 Node* label = environment()->Pop(); | 553 Node* label = environment()->Pop(); |
554 Operator* op = javascript()->StrictEqual(); | 554 const Operator* op = javascript()->StrictEqual(); |
555 Node* condition = NewNode(op, tag, label); | 555 Node* condition = NewNode(op, tag, label); |
556 compare_switch.BeginLabel(i, condition); | 556 compare_switch.BeginLabel(i, condition); |
557 | 557 |
558 // Discard the switch value at label match. | 558 // Discard the switch value at label match. |
559 environment()->Pop(); | 559 environment()->Pop(); |
560 compare_switch.EndLabel(); | 560 compare_switch.EndLabel(); |
561 } | 561 } |
562 | 562 |
563 // Discard the switch value and mark the default case. | 563 // Discard the switch value and mark the default case. |
564 environment()->Pop(); | 564 environment()->Pop(); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); | 799 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); |
800 if (shared_info.is_null()) { | 800 if (shared_info.is_null()) { |
801 shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info()); | 801 shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info()); |
802 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow? | 802 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow? |
803 } | 803 } |
804 | 804 |
805 // Create node to instantiate a new closure. | 805 // Create node to instantiate a new closure. |
806 Node* info = jsgraph()->Constant(shared_info); | 806 Node* info = jsgraph()->Constant(shared_info); |
807 Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant() | 807 Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant() |
808 : jsgraph()->FalseConstant(); | 808 : jsgraph()->FalseConstant(); |
809 Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3); | 809 const Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3); |
810 Node* value = NewNode(op, context, info, pretenure); | 810 Node* value = NewNode(op, context, info, pretenure); |
811 ast_context()->ProduceValue(value); | 811 ast_context()->ProduceValue(value); |
812 } | 812 } |
813 | 813 |
814 | 814 |
815 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 815 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
816 UNREACHABLE(); | 816 UNREACHABLE(); |
817 } | 817 } |
818 | 818 |
819 | 819 |
(...skipping 25 matching lines...) Expand all Loading... |
845 | 845 |
846 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 846 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
847 Node* closure = GetFunctionClosure(); | 847 Node* closure = GetFunctionClosure(); |
848 | 848 |
849 // Create node to materialize a regular expression literal. | 849 // Create node to materialize a regular expression literal. |
850 Node* literals_array = | 850 Node* literals_array = |
851 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); | 851 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); |
852 Node* literal_index = jsgraph()->Constant(expr->literal_index()); | 852 Node* literal_index = jsgraph()->Constant(expr->literal_index()); |
853 Node* pattern = jsgraph()->Constant(expr->pattern()); | 853 Node* pattern = jsgraph()->Constant(expr->pattern()); |
854 Node* flags = jsgraph()->Constant(expr->flags()); | 854 Node* flags = jsgraph()->Constant(expr->flags()); |
855 Operator* op = javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); | 855 const Operator* op = |
| 856 javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); |
856 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); | 857 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); |
857 ast_context()->ProduceValue(literal); | 858 ast_context()->ProduceValue(literal); |
858 } | 859 } |
859 | 860 |
860 | 861 |
861 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 862 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
862 Node* closure = GetFunctionClosure(); | 863 Node* closure = GetFunctionClosure(); |
863 | 864 |
864 // Create node to deep-copy the literal boilerplate. | 865 // Create node to deep-copy the literal boilerplate. |
865 expr->BuildConstantProperties(isolate()); | 866 expr->BuildConstantProperties(isolate()); |
866 Node* literals_array = | 867 Node* literals_array = |
867 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); | 868 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); |
868 Node* literal_index = jsgraph()->Constant(expr->literal_index()); | 869 Node* literal_index = jsgraph()->Constant(expr->literal_index()); |
869 Node* constants = jsgraph()->Constant(expr->constant_properties()); | 870 Node* constants = jsgraph()->Constant(expr->constant_properties()); |
870 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); | 871 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); |
871 Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4); | 872 const Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4); |
872 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); | 873 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); |
873 | 874 |
874 // The object is expected on the operand stack during computation of the | 875 // The object is expected on the operand stack during computation of the |
875 // property values and is the value of the entire expression. | 876 // property values and is the value of the entire expression. |
876 environment()->Push(literal); | 877 environment()->Push(literal); |
877 | 878 |
878 // Mark all computed expressions that are bound to a key that is shadowed by | 879 // Mark all computed expressions that are bound to a key that is shadowed by |
879 // a later occurrence of the same key. For the marked expressions, no store | 880 // a later occurrence of the same key. For the marked expressions, no store |
880 // code is emitted. | 881 // code is emitted. |
881 expr->CalculateEmitStore(zone()); | 882 expr->CalculateEmitStore(zone()); |
(...skipping 28 matching lines...) Expand all Loading... |
910 break; | 911 break; |
911 } | 912 } |
912 environment()->Push(literal); // Duplicate receiver. | 913 environment()->Push(literal); // Duplicate receiver. |
913 VisitForValue(property->key()); | 914 VisitForValue(property->key()); |
914 VisitForValue(property->value()); | 915 VisitForValue(property->value()); |
915 Node* value = environment()->Pop(); | 916 Node* value = environment()->Pop(); |
916 Node* key = environment()->Pop(); | 917 Node* key = environment()->Pop(); |
917 Node* receiver = environment()->Pop(); | 918 Node* receiver = environment()->Pop(); |
918 if (property->emit_store()) { | 919 if (property->emit_store()) { |
919 Node* strict = jsgraph()->Constant(SLOPPY); | 920 Node* strict = jsgraph()->Constant(SLOPPY); |
920 Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4); | 921 const Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4); |
921 NewNode(op, receiver, key, value, strict); | 922 NewNode(op, receiver, key, value, strict); |
922 } | 923 } |
923 break; | 924 break; |
924 } | 925 } |
925 case ObjectLiteral::Property::PROTOTYPE: { | 926 case ObjectLiteral::Property::PROTOTYPE: { |
926 environment()->Push(literal); // Duplicate receiver. | 927 environment()->Push(literal); // Duplicate receiver. |
927 VisitForValue(property->value()); | 928 VisitForValue(property->value()); |
928 Node* value = environment()->Pop(); | 929 Node* value = environment()->Pop(); |
929 Node* receiver = environment()->Pop(); | 930 Node* receiver = environment()->Pop(); |
930 if (property->emit_store()) { | 931 if (property->emit_store()) { |
931 Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2); | 932 const Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2); |
932 NewNode(op, receiver, value); | 933 NewNode(op, receiver, value); |
933 } | 934 } |
934 break; | 935 break; |
935 } | 936 } |
936 case ObjectLiteral::Property::GETTER: | 937 case ObjectLiteral::Property::GETTER: |
937 accessor_table.lookup(key)->second->getter = property->value(); | 938 accessor_table.lookup(key)->second->getter = property->value(); |
938 break; | 939 break; |
939 case ObjectLiteral::Property::SETTER: | 940 case ObjectLiteral::Property::SETTER: |
940 accessor_table.lookup(key)->second->setter = property->value(); | 941 accessor_table.lookup(key)->second->setter = property->value(); |
941 break; | 942 break; |
942 } | 943 } |
943 } | 944 } |
944 | 945 |
945 // Create nodes to define accessors, using only a single call to the runtime | 946 // Create nodes to define accessors, using only a single call to the runtime |
946 // for each pair of corresponding getters and setters. | 947 // for each pair of corresponding getters and setters. |
947 for (AccessorTable::Iterator it = accessor_table.begin(); | 948 for (AccessorTable::Iterator it = accessor_table.begin(); |
948 it != accessor_table.end(); ++it) { | 949 it != accessor_table.end(); ++it) { |
949 VisitForValue(it->first); | 950 VisitForValue(it->first); |
950 VisitForValueOrNull(it->second->getter); | 951 VisitForValueOrNull(it->second->getter); |
951 VisitForValueOrNull(it->second->setter); | 952 VisitForValueOrNull(it->second->setter); |
952 Node* setter = environment()->Pop(); | 953 Node* setter = environment()->Pop(); |
953 Node* getter = environment()->Pop(); | 954 Node* getter = environment()->Pop(); |
954 Node* name = environment()->Pop(); | 955 Node* name = environment()->Pop(); |
955 Node* attr = jsgraph()->Constant(NONE); | 956 Node* attr = jsgraph()->Constant(NONE); |
956 Operator* op = | 957 const Operator* op = |
957 javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 958 javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
958 NewNode(op, literal, name, getter, setter, attr); | 959 NewNode(op, literal, name, getter, setter, attr); |
959 } | 960 } |
960 | 961 |
961 // Transform literals that contain functions to fast properties. | 962 // Transform literals that contain functions to fast properties. |
962 if (expr->has_function()) { | 963 if (expr->has_function()) { |
963 Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1); | 964 const Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1); |
964 NewNode(op, literal); | 965 NewNode(op, literal); |
965 } | 966 } |
966 | 967 |
967 ast_context()->ProduceValue(environment()->Pop()); | 968 ast_context()->ProduceValue(environment()->Pop()); |
968 } | 969 } |
969 | 970 |
970 | 971 |
971 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 972 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
972 Node* closure = GetFunctionClosure(); | 973 Node* closure = GetFunctionClosure(); |
973 | 974 |
974 // Create node to deep-copy the literal boilerplate. | 975 // Create node to deep-copy the literal boilerplate. |
975 expr->BuildConstantElements(isolate()); | 976 expr->BuildConstantElements(isolate()); |
976 Node* literals_array = | 977 Node* literals_array = |
977 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); | 978 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); |
978 Node* literal_index = jsgraph()->Constant(expr->literal_index()); | 979 Node* literal_index = jsgraph()->Constant(expr->literal_index()); |
979 Node* constants = jsgraph()->Constant(expr->constant_elements()); | 980 Node* constants = jsgraph()->Constant(expr->constant_elements()); |
980 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); | 981 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); |
981 Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4); | 982 const Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4); |
982 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); | 983 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); |
983 | 984 |
984 // The array and the literal index are both expected on the operand stack | 985 // The array and the literal index are both expected on the operand stack |
985 // during computation of the element values. | 986 // during computation of the element values. |
986 environment()->Push(literal); | 987 environment()->Push(literal); |
987 environment()->Push(literal_index); | 988 environment()->Push(literal_index); |
988 | 989 |
989 // Create nodes to evaluate all the non-constant subexpressions and to store | 990 // Create nodes to evaluate all the non-constant subexpressions and to store |
990 // them into the newly cloned array. | 991 // them into the newly cloned array. |
991 for (int i = 0; i < expr->values()->length(); i++) { | 992 for (int i = 0; i < expr->values()->length(); i++) { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 environment()->Pop(); | 1148 environment()->Pop(); |
1148 environment()->Pop(); | 1149 environment()->Pop(); |
1149 // TODO(turbofan): VisitYield | 1150 // TODO(turbofan): VisitYield |
1150 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); | 1151 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); |
1151 } | 1152 } |
1152 | 1153 |
1153 | 1154 |
1154 void AstGraphBuilder::VisitThrow(Throw* expr) { | 1155 void AstGraphBuilder::VisitThrow(Throw* expr) { |
1155 VisitForValue(expr->exception()); | 1156 VisitForValue(expr->exception()); |
1156 Node* exception = environment()->Pop(); | 1157 Node* exception = environment()->Pop(); |
1157 Operator* op = javascript()->Runtime(Runtime::kThrow, 1); | 1158 const Operator* op = javascript()->Runtime(Runtime::kThrow, 1); |
1158 Node* value = NewNode(op, exception); | 1159 Node* value = NewNode(op, exception); |
1159 ast_context()->ProduceValue(value); | 1160 ast_context()->ProduceValue(value); |
1160 } | 1161 } |
1161 | 1162 |
1162 | 1163 |
1163 void AstGraphBuilder::VisitProperty(Property* expr) { | 1164 void AstGraphBuilder::VisitProperty(Property* expr) { |
1164 Node* value; | 1165 Node* value; |
1165 if (expr->key()->IsPropertyName()) { | 1166 if (expr->key()->IsPropertyName()) { |
1166 VisitForValue(expr->obj()); | 1167 VisitForValue(expr->obj()); |
1167 Node* object = environment()->Pop(); | 1168 Node* object = environment()->Pop(); |
(...skipping 25 matching lines...) Expand all Loading... |
1193 case Call::GLOBAL_CALL: { | 1194 case Call::GLOBAL_CALL: { |
1194 Variable* variable = callee->AsVariableProxy()->var(); | 1195 Variable* variable = callee->AsVariableProxy()->var(); |
1195 callee_value = BuildVariableLoad(variable, expr->expression()->id()); | 1196 callee_value = BuildVariableLoad(variable, expr->expression()->id()); |
1196 receiver_value = jsgraph()->UndefinedConstant(); | 1197 receiver_value = jsgraph()->UndefinedConstant(); |
1197 break; | 1198 break; |
1198 } | 1199 } |
1199 case Call::LOOKUP_SLOT_CALL: { | 1200 case Call::LOOKUP_SLOT_CALL: { |
1200 Variable* variable = callee->AsVariableProxy()->var(); | 1201 Variable* variable = callee->AsVariableProxy()->var(); |
1201 DCHECK(variable->location() == Variable::LOOKUP); | 1202 DCHECK(variable->location() == Variable::LOOKUP); |
1202 Node* name = jsgraph()->Constant(variable->name()); | 1203 Node* name = jsgraph()->Constant(variable->name()); |
1203 Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); | 1204 const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); |
1204 Node* pair = NewNode(op, current_context(), name); | 1205 Node* pair = NewNode(op, current_context(), name); |
1205 callee_value = NewNode(common()->Projection(0), pair); | 1206 callee_value = NewNode(common()->Projection(0), pair); |
1206 receiver_value = NewNode(common()->Projection(1), pair); | 1207 receiver_value = NewNode(common()->Projection(1), pair); |
1207 break; | 1208 break; |
1208 } | 1209 } |
1209 case Call::PROPERTY_CALL: { | 1210 case Call::PROPERTY_CALL: { |
1210 Property* property = callee->AsProperty(); | 1211 Property* property = callee->AsProperty(); |
1211 VisitForValue(property->obj()); | 1212 VisitForValue(property->obj()); |
1212 Node* object = environment()->Top(); | 1213 Node* object = environment()->Top(); |
1213 if (property->key()->IsPropertyName()) { | 1214 if (property->key()->IsPropertyName()) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 | 1254 |
1254 // Extract callee and source string from the environment. | 1255 // Extract callee and source string from the environment. |
1255 Node* callee = environment()->Peek(arg_count + 1); | 1256 Node* callee = environment()->Peek(arg_count + 1); |
1256 Node* source = environment()->Peek(arg_count - 1); | 1257 Node* source = environment()->Peek(arg_count - 1); |
1257 | 1258 |
1258 // Create node to ask for help resolving potential eval call. This will | 1259 // Create node to ask for help resolving potential eval call. This will |
1259 // provide a fully resolved callee and the corresponding receiver. | 1260 // provide a fully resolved callee and the corresponding receiver. |
1260 Node* receiver = environment()->Lookup(info()->scope()->receiver()); | 1261 Node* receiver = environment()->Lookup(info()->scope()->receiver()); |
1261 Node* strict = jsgraph()->Constant(strict_mode()); | 1262 Node* strict = jsgraph()->Constant(strict_mode()); |
1262 Node* position = jsgraph()->Constant(info()->scope()->start_position()); | 1263 Node* position = jsgraph()->Constant(info()->scope()->start_position()); |
1263 Operator* op = | 1264 const Operator* op = |
1264 javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5); | 1265 javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5); |
1265 Node* pair = NewNode(op, callee, source, receiver, strict, position); | 1266 Node* pair = NewNode(op, callee, source, receiver, strict, position); |
1266 Node* new_callee = NewNode(common()->Projection(0), pair); | 1267 Node* new_callee = NewNode(common()->Projection(0), pair); |
1267 Node* new_receiver = NewNode(common()->Projection(1), pair); | 1268 Node* new_receiver = NewNode(common()->Projection(1), pair); |
1268 | 1269 |
1269 // Patch callee and receiver on the environment. | 1270 // Patch callee and receiver on the environment. |
1270 environment()->Poke(arg_count + 1, new_callee); | 1271 environment()->Poke(arg_count + 1, new_callee); |
1271 environment()->Poke(arg_count + 0, new_receiver); | 1272 environment()->Poke(arg_count + 0, new_receiver); |
1272 } | 1273 } |
1273 | 1274 |
1274 // Create node to perform the function call. | 1275 // Create node to perform the function call. |
1275 Operator* call = javascript()->Call(args->length() + 2, flags); | 1276 const Operator* call = javascript()->Call(args->length() + 2, flags); |
1276 Node* value = ProcessArguments(call, args->length() + 2); | 1277 Node* value = ProcessArguments(call, args->length() + 2); |
1277 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1278 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1278 ast_context()->ProduceValue(value); | 1279 ast_context()->ProduceValue(value); |
1279 } | 1280 } |
1280 | 1281 |
1281 | 1282 |
1282 void AstGraphBuilder::VisitCallNew(CallNew* expr) { | 1283 void AstGraphBuilder::VisitCallNew(CallNew* expr) { |
1283 VisitForValue(expr->expression()); | 1284 VisitForValue(expr->expression()); |
1284 | 1285 |
1285 // Evaluate all arguments to the construct call. | 1286 // Evaluate all arguments to the construct call. |
1286 ZoneList<Expression*>* args = expr->arguments(); | 1287 ZoneList<Expression*>* args = expr->arguments(); |
1287 VisitForValues(args); | 1288 VisitForValues(args); |
1288 | 1289 |
1289 // Create node to perform the construct call. | 1290 // Create node to perform the construct call. |
1290 Operator* call = javascript()->CallNew(args->length() + 1); | 1291 const Operator* call = javascript()->CallNew(args->length() + 1); |
1291 Node* value = ProcessArguments(call, args->length() + 1); | 1292 Node* value = ProcessArguments(call, args->length() + 1); |
1292 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1293 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1293 ast_context()->ProduceValue(value); | 1294 ast_context()->ProduceValue(value); |
1294 } | 1295 } |
1295 | 1296 |
1296 | 1297 |
1297 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { | 1298 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { |
1298 Handle<String> name = expr->name(); | 1299 Handle<String> name = expr->name(); |
1299 | 1300 |
1300 // The callee and the receiver both have to be pushed onto the operand stack | 1301 // The callee and the receiver both have to be pushed onto the operand stack |
1301 // before arguments are being evaluated. | 1302 // before arguments are being evaluated. |
1302 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1303 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
1303 Node* receiver_value = BuildLoadBuiltinsObject(); | 1304 Node* receiver_value = BuildLoadBuiltinsObject(); |
1304 Unique<String> unique = MakeUnique(name); | 1305 Unique<String> unique = MakeUnique(name); |
1305 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); | 1306 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); |
1306 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft | 1307 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft |
1307 // refuses to optimize functions with jsruntime calls). | 1308 // refuses to optimize functions with jsruntime calls). |
1308 PrepareFrameState(callee_value, BailoutId::None(), kPushOutput); | 1309 PrepareFrameState(callee_value, BailoutId::None(), kPushOutput); |
1309 environment()->Push(callee_value); | 1310 environment()->Push(callee_value); |
1310 environment()->Push(receiver_value); | 1311 environment()->Push(receiver_value); |
1311 | 1312 |
1312 // Evaluate all arguments to the JS runtime call. | 1313 // Evaluate all arguments to the JS runtime call. |
1313 ZoneList<Expression*>* args = expr->arguments(); | 1314 ZoneList<Expression*>* args = expr->arguments(); |
1314 VisitForValues(args); | 1315 VisitForValues(args); |
1315 | 1316 |
1316 // Create node to perform the JS runtime call. | 1317 // Create node to perform the JS runtime call. |
1317 Operator* call = javascript()->Call(args->length() + 2, flags); | 1318 const Operator* call = javascript()->Call(args->length() + 2, flags); |
1318 Node* value = ProcessArguments(call, args->length() + 2); | 1319 Node* value = ProcessArguments(call, args->length() + 2); |
1319 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1320 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1320 ast_context()->ProduceValue(value); | 1321 ast_context()->ProduceValue(value); |
1321 } | 1322 } |
1322 | 1323 |
1323 | 1324 |
1324 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 1325 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
1325 const Runtime::Function* function = expr->function(); | 1326 const Runtime::Function* function = expr->function(); |
1326 | 1327 |
1327 // Handle calls to runtime functions implemented in JavaScript separately as | 1328 // Handle calls to runtime functions implemented in JavaScript separately as |
1328 // the call follows JavaScript ABI and the callee is statically unknown. | 1329 // the call follows JavaScript ABI and the callee is statically unknown. |
1329 if (expr->is_jsruntime()) { | 1330 if (expr->is_jsruntime()) { |
1330 DCHECK(function == NULL && expr->name()->length() > 0); | 1331 DCHECK(function == NULL && expr->name()->length() > 0); |
1331 return VisitCallJSRuntime(expr); | 1332 return VisitCallJSRuntime(expr); |
1332 } | 1333 } |
1333 | 1334 |
1334 // Evaluate all arguments to the runtime call. | 1335 // Evaluate all arguments to the runtime call. |
1335 ZoneList<Expression*>* args = expr->arguments(); | 1336 ZoneList<Expression*>* args = expr->arguments(); |
1336 VisitForValues(args); | 1337 VisitForValues(args); |
1337 | 1338 |
1338 // Create node to perform the runtime call. | 1339 // Create node to perform the runtime call. |
1339 Runtime::FunctionId functionId = function->function_id; | 1340 Runtime::FunctionId functionId = function->function_id; |
1340 Operator* call = javascript()->Runtime(functionId, args->length()); | 1341 const Operator* call = javascript()->Runtime(functionId, args->length()); |
1341 Node* value = ProcessArguments(call, args->length()); | 1342 Node* value = ProcessArguments(call, args->length()); |
1342 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1343 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1343 ast_context()->ProduceValue(value); | 1344 ast_context()->ProduceValue(value); |
1344 } | 1345 } |
1345 | 1346 |
1346 | 1347 |
1347 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 1348 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
1348 switch (expr->op()) { | 1349 switch (expr->op()) { |
1349 case Token::DELETE: | 1350 case Token::DELETE: |
1350 return VisitDelete(expr); | 1351 return VisitDelete(expr); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 Node* left = environment()->Pop(); | 1465 Node* left = environment()->Pop(); |
1465 Node* value = BuildBinaryOp(left, right, expr->op()); | 1466 Node* value = BuildBinaryOp(left, right, expr->op()); |
1466 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1467 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1467 ast_context()->ProduceValue(value); | 1468 ast_context()->ProduceValue(value); |
1468 } | 1469 } |
1469 } | 1470 } |
1470 } | 1471 } |
1471 | 1472 |
1472 | 1473 |
1473 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 1474 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
1474 Operator* op; | 1475 const Operator* op; |
1475 switch (expr->op()) { | 1476 switch (expr->op()) { |
1476 case Token::EQ: | 1477 case Token::EQ: |
1477 op = javascript()->Equal(); | 1478 op = javascript()->Equal(); |
1478 break; | 1479 break; |
1479 case Token::NE: | 1480 case Token::NE: |
1480 op = javascript()->NotEqual(); | 1481 op = javascript()->NotEqual(); |
1481 break; | 1482 break; |
1482 case Token::EQ_STRICT: | 1483 case Token::EQ_STRICT: |
1483 op = javascript()->StrictEqual(); | 1484 op = javascript()->StrictEqual(); |
1484 break; | 1485 break; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 AstVisitor::VisitDeclarations(declarations); | 1537 AstVisitor::VisitDeclarations(declarations); |
1537 if (globals()->is_empty()) return; | 1538 if (globals()->is_empty()) return; |
1538 Handle<FixedArray> data = | 1539 Handle<FixedArray> data = |
1539 isolate()->factory()->NewFixedArray(globals()->length(), TENURED); | 1540 isolate()->factory()->NewFixedArray(globals()->length(), TENURED); |
1540 for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i)); | 1541 for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i)); |
1541 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 1542 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
1542 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 1543 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
1543 DeclareGlobalsStrictMode::encode(strict_mode()); | 1544 DeclareGlobalsStrictMode::encode(strict_mode()); |
1544 Node* flags = jsgraph()->Constant(encoded_flags); | 1545 Node* flags = jsgraph()->Constant(encoded_flags); |
1545 Node* pairs = jsgraph()->Constant(data); | 1546 Node* pairs = jsgraph()->Constant(data); |
1546 Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3); | 1547 const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3); |
1547 NewNode(op, current_context(), pairs, flags); | 1548 NewNode(op, current_context(), pairs, flags); |
1548 globals()->Rewind(0); | 1549 globals()->Rewind(0); |
1549 } | 1550 } |
1550 | 1551 |
1551 | 1552 |
1552 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { | 1553 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { |
1553 if (stmt == NULL) return; | 1554 if (stmt == NULL) return; |
1554 Visit(stmt); | 1555 Visit(stmt); |
1555 } | 1556 } |
1556 | 1557 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 environment()->Pop(); | 1644 environment()->Pop(); |
1644 Visit(expr->right()); | 1645 Visit(expr->right()); |
1645 } else if (ast_context()->IsEffect()) { | 1646 } else if (ast_context()->IsEffect()) { |
1646 environment()->Pop(); | 1647 environment()->Pop(); |
1647 } | 1648 } |
1648 compare_if.End(); | 1649 compare_if.End(); |
1649 ast_context()->ReplaceValue(); | 1650 ast_context()->ReplaceValue(); |
1650 } | 1651 } |
1651 | 1652 |
1652 | 1653 |
1653 Node* AstGraphBuilder::ProcessArguments(Operator* op, int arity) { | 1654 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { |
1654 DCHECK(environment()->stack_height() >= arity); | 1655 DCHECK(environment()->stack_height() >= arity); |
1655 Node** all = info()->zone()->NewArray<Node*>(arity); | 1656 Node** all = info()->zone()->NewArray<Node*>(arity); |
1656 for (int i = arity - 1; i >= 0; --i) { | 1657 for (int i = arity - 1; i >= 0; --i) { |
1657 all[i] = environment()->Pop(); | 1658 all[i] = environment()->Pop(); |
1658 } | 1659 } |
1659 Node* value = NewNode(op, arity, all); | 1660 Node* value = NewNode(op, arity, all); |
1660 return value; | 1661 return value; |
1661 } | 1662 } |
1662 | 1663 |
1663 | 1664 |
1664 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { | 1665 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { |
1665 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 1666 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
1666 if (heap_slots <= 0) return context; | 1667 if (heap_slots <= 0) return context; |
1667 set_current_context(context); | 1668 set_current_context(context); |
1668 | 1669 |
1669 // Allocate a new local context. | 1670 // Allocate a new local context. |
1670 Operator* op = javascript()->CreateFunctionContext(); | 1671 const Operator* op = javascript()->CreateFunctionContext(); |
1671 Node* local_context = NewNode(op, closure); | 1672 Node* local_context = NewNode(op, closure); |
1672 set_current_context(local_context); | 1673 set_current_context(local_context); |
1673 | 1674 |
1674 // Copy parameters into context if necessary. | 1675 // Copy parameters into context if necessary. |
1675 int num_parameters = info()->scope()->num_parameters(); | 1676 int num_parameters = info()->scope()->num_parameters(); |
1676 for (int i = 0; i < num_parameters; i++) { | 1677 for (int i = 0; i < num_parameters; i++) { |
1677 Variable* variable = info()->scope()->parameter(i); | 1678 Variable* variable = info()->scope()->parameter(i); |
1678 if (!variable->IsContextSlot()) continue; | 1679 if (!variable->IsContextSlot()) continue; |
1679 // Temporary parameter node. The parameter indices are shifted by 1 | 1680 // Temporary parameter node. The parameter indices are shifted by 1 |
1680 // (receiver is parameter index -1 but environment index 0). | 1681 // (receiver is parameter index -1 but environment index 0). |
1681 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); | 1682 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); |
1682 // Context variable (at bottom of the context chain). | 1683 // Context variable (at bottom of the context chain). |
1683 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); | 1684 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); |
1684 Operator* op = javascript()->StoreContext(0, variable->index()); | 1685 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1685 NewNode(op, local_context, parameter); | 1686 NewNode(op, local_context, parameter); |
1686 } | 1687 } |
1687 | 1688 |
1688 return local_context; | 1689 return local_context; |
1689 } | 1690 } |
1690 | 1691 |
1691 | 1692 |
1692 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { | 1693 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
1693 if (arguments == NULL) return NULL; | 1694 if (arguments == NULL) return NULL; |
1694 | 1695 |
1695 // Allocate and initialize a new arguments object. | 1696 // Allocate and initialize a new arguments object. |
1696 Node* callee = GetFunctionClosure(); | 1697 Node* callee = GetFunctionClosure(); |
1697 Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); | 1698 const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); |
1698 Node* object = NewNode(op, callee); | 1699 Node* object = NewNode(op, callee); |
1699 | 1700 |
1700 // Assign the object to the arguments variable. | 1701 // Assign the object to the arguments variable. |
1701 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 1702 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
1702 // This should never lazy deopt, so it is fine to send invalid bailout id. | 1703 // This should never lazy deopt, so it is fine to send invalid bailout id. |
1703 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); | 1704 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); |
1704 | 1705 |
1705 return object; | 1706 return object; |
1706 } | 1707 } |
1707 | 1708 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, | 1740 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
1740 BailoutId bailout_id, | 1741 BailoutId bailout_id, |
1741 ContextualMode contextual_mode) { | 1742 ContextualMode contextual_mode) { |
1742 Node* the_hole = jsgraph()->TheHoleConstant(); | 1743 Node* the_hole = jsgraph()->TheHoleConstant(); |
1743 VariableMode mode = variable->mode(); | 1744 VariableMode mode = variable->mode(); |
1744 switch (variable->location()) { | 1745 switch (variable->location()) { |
1745 case Variable::UNALLOCATED: { | 1746 case Variable::UNALLOCATED: { |
1746 // Global var, const, or let variable. | 1747 // Global var, const, or let variable. |
1747 Node* global = BuildLoadGlobalObject(); | 1748 Node* global = BuildLoadGlobalObject(); |
1748 Unique<Name> name = MakeUnique(variable->name()); | 1749 Unique<Name> name = MakeUnique(variable->name()); |
1749 Operator* op = javascript()->LoadNamed(name, contextual_mode); | 1750 const Operator* op = javascript()->LoadNamed(name, contextual_mode); |
1750 Node* node = NewNode(op, global); | 1751 Node* node = NewNode(op, global); |
1751 PrepareFrameState(node, bailout_id, kPushOutput); | 1752 PrepareFrameState(node, bailout_id, kPushOutput); |
1752 return node; | 1753 return node; |
1753 } | 1754 } |
1754 case Variable::PARAMETER: | 1755 case Variable::PARAMETER: |
1755 case Variable::LOCAL: { | 1756 case Variable::LOCAL: { |
1756 // Local var, const, or let variable. | 1757 // Local var, const, or let variable. |
1757 Node* value = environment()->Lookup(variable); | 1758 Node* value = environment()->Lookup(variable); |
1758 if (mode == CONST_LEGACY) { | 1759 if (mode == CONST_LEGACY) { |
1759 // Perform check for uninitialized legacy const variables. | 1760 // Perform check for uninitialized legacy const variables. |
(...skipping 10 matching lines...) Expand all Loading... |
1770 } else if (value->opcode() == IrOpcode::kPhi) { | 1771 } else if (value->opcode() == IrOpcode::kPhi) { |
1771 value = BuildHoleCheckThrow(value, variable, value); | 1772 value = BuildHoleCheckThrow(value, variable, value); |
1772 } | 1773 } |
1773 } | 1774 } |
1774 return value; | 1775 return value; |
1775 } | 1776 } |
1776 case Variable::CONTEXT: { | 1777 case Variable::CONTEXT: { |
1777 // Context variable (potentially up the context chain). | 1778 // Context variable (potentially up the context chain). |
1778 int depth = current_scope()->ContextChainLength(variable->scope()); | 1779 int depth = current_scope()->ContextChainLength(variable->scope()); |
1779 bool immutable = variable->maybe_assigned() == kNotAssigned; | 1780 bool immutable = variable->maybe_assigned() == kNotAssigned; |
1780 Operator* op = | 1781 const Operator* op = |
1781 javascript()->LoadContext(depth, variable->index(), immutable); | 1782 javascript()->LoadContext(depth, variable->index(), immutable); |
1782 Node* value = NewNode(op, current_context()); | 1783 Node* value = NewNode(op, current_context()); |
1783 // TODO(titzer): initialization checks are redundant for already | 1784 // TODO(titzer): initialization checks are redundant for already |
1784 // initialized immutable context loads, but only specialization knows. | 1785 // initialized immutable context loads, but only specialization knows. |
1785 // Maybe specializer should be a parameter to the graph builder? | 1786 // Maybe specializer should be a parameter to the graph builder? |
1786 if (mode == CONST_LEGACY) { | 1787 if (mode == CONST_LEGACY) { |
1787 // Perform check for uninitialized legacy const variables. | 1788 // Perform check for uninitialized legacy const variables. |
1788 Node* undefined = jsgraph()->UndefinedConstant(); | 1789 Node* undefined = jsgraph()->UndefinedConstant(); |
1789 value = BuildHoleCheckSilent(value, undefined, value); | 1790 value = BuildHoleCheckSilent(value, undefined, value); |
1790 } else if (mode == LET || mode == CONST) { | 1791 } else if (mode == LET || mode == CONST) { |
1791 // Perform check for uninitialized let/const variables. | 1792 // Perform check for uninitialized let/const variables. |
1792 value = BuildHoleCheckThrow(value, variable, value); | 1793 value = BuildHoleCheckThrow(value, variable, value); |
1793 } | 1794 } |
1794 return value; | 1795 return value; |
1795 } | 1796 } |
1796 case Variable::LOOKUP: { | 1797 case Variable::LOOKUP: { |
1797 // Dynamic lookup of context variable (anywhere in the chain). | 1798 // Dynamic lookup of context variable (anywhere in the chain). |
1798 Node* name = jsgraph()->Constant(variable->name()); | 1799 Node* name = jsgraph()->Constant(variable->name()); |
1799 Runtime::FunctionId function_id = | 1800 Runtime::FunctionId function_id = |
1800 (contextual_mode == CONTEXTUAL) | 1801 (contextual_mode == CONTEXTUAL) |
1801 ? Runtime::kLoadLookupSlot | 1802 ? Runtime::kLoadLookupSlot |
1802 : Runtime::kLoadLookupSlotNoReferenceError; | 1803 : Runtime::kLoadLookupSlotNoReferenceError; |
1803 Operator* op = javascript()->Runtime(function_id, 2); | 1804 const Operator* op = javascript()->Runtime(function_id, 2); |
1804 Node* pair = NewNode(op, current_context(), name); | 1805 Node* pair = NewNode(op, current_context(), name); |
1805 return NewNode(common()->Projection(0), pair); | 1806 return NewNode(common()->Projection(0), pair); |
1806 } | 1807 } |
1807 } | 1808 } |
1808 UNREACHABLE(); | 1809 UNREACHABLE(); |
1809 return NULL; | 1810 return NULL; |
1810 } | 1811 } |
1811 | 1812 |
1812 | 1813 |
1813 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) { | 1814 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) { |
1814 switch (variable->location()) { | 1815 switch (variable->location()) { |
1815 case Variable::UNALLOCATED: { | 1816 case Variable::UNALLOCATED: { |
1816 // Global var, const, or let variable. | 1817 // Global var, const, or let variable. |
1817 Node* global = BuildLoadGlobalObject(); | 1818 Node* global = BuildLoadGlobalObject(); |
1818 Node* name = jsgraph()->Constant(variable->name()); | 1819 Node* name = jsgraph()->Constant(variable->name()); |
1819 Operator* op = javascript()->DeleteProperty(strict_mode()); | 1820 const Operator* op = javascript()->DeleteProperty(strict_mode()); |
1820 return NewNode(op, global, name); | 1821 return NewNode(op, global, name); |
1821 } | 1822 } |
1822 case Variable::PARAMETER: | 1823 case Variable::PARAMETER: |
1823 case Variable::LOCAL: | 1824 case Variable::LOCAL: |
1824 case Variable::CONTEXT: | 1825 case Variable::CONTEXT: |
1825 // Local var, const, or let variable or context variable. | 1826 // Local var, const, or let variable or context variable. |
1826 return variable->is_this() ? jsgraph()->TrueConstant() | 1827 return variable->is_this() ? jsgraph()->TrueConstant() |
1827 : jsgraph()->FalseConstant(); | 1828 : jsgraph()->FalseConstant(); |
1828 case Variable::LOOKUP: { | 1829 case Variable::LOOKUP: { |
1829 // Dynamic lookup of context variable (anywhere in the chain). | 1830 // Dynamic lookup of context variable (anywhere in the chain). |
1830 Node* name = jsgraph()->Constant(variable->name()); | 1831 Node* name = jsgraph()->Constant(variable->name()); |
1831 Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); | 1832 const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); |
1832 return NewNode(op, current_context(), name); | 1833 return NewNode(op, current_context(), name); |
1833 } | 1834 } |
1834 } | 1835 } |
1835 UNREACHABLE(); | 1836 UNREACHABLE(); |
1836 return NULL; | 1837 return NULL; |
1837 } | 1838 } |
1838 | 1839 |
1839 | 1840 |
1840 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, | 1841 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, |
1841 Token::Value op, | 1842 Token::Value op, |
1842 BailoutId bailout_id) { | 1843 BailoutId bailout_id) { |
1843 Node* the_hole = jsgraph()->TheHoleConstant(); | 1844 Node* the_hole = jsgraph()->TheHoleConstant(); |
1844 VariableMode mode = variable->mode(); | 1845 VariableMode mode = variable->mode(); |
1845 switch (variable->location()) { | 1846 switch (variable->location()) { |
1846 case Variable::UNALLOCATED: { | 1847 case Variable::UNALLOCATED: { |
1847 // Global var, const, or let variable. | 1848 // Global var, const, or let variable. |
1848 Node* global = BuildLoadGlobalObject(); | 1849 Node* global = BuildLoadGlobalObject(); |
1849 Unique<Name> name = MakeUnique(variable->name()); | 1850 Unique<Name> name = MakeUnique(variable->name()); |
1850 Operator* op = javascript()->StoreNamed(strict_mode(), name); | 1851 const Operator* op = javascript()->StoreNamed(strict_mode(), name); |
1851 Node* store = NewNode(op, global, value); | 1852 Node* store = NewNode(op, global, value); |
1852 PrepareFrameState(store, bailout_id); | 1853 PrepareFrameState(store, bailout_id); |
1853 return store; | 1854 return store; |
1854 } | 1855 } |
1855 case Variable::PARAMETER: | 1856 case Variable::PARAMETER: |
1856 case Variable::LOCAL: | 1857 case Variable::LOCAL: |
1857 // Local var, const, or let variable. | 1858 // Local var, const, or let variable. |
1858 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 1859 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
1859 // Perform an initialization check for legacy const variables. | 1860 // Perform an initialization check for legacy const variables. |
1860 Node* current = environment()->Lookup(variable); | 1861 Node* current = environment()->Lookup(variable); |
(...skipping 18 matching lines...) Expand all Loading... |
1879 // All assignments to const variables are early errors. | 1880 // All assignments to const variables are early errors. |
1880 UNREACHABLE(); | 1881 UNREACHABLE(); |
1881 } | 1882 } |
1882 environment()->Bind(variable, value); | 1883 environment()->Bind(variable, value); |
1883 return value; | 1884 return value; |
1884 case Variable::CONTEXT: { | 1885 case Variable::CONTEXT: { |
1885 // Context variable (potentially up the context chain). | 1886 // Context variable (potentially up the context chain). |
1886 int depth = current_scope()->ContextChainLength(variable->scope()); | 1887 int depth = current_scope()->ContextChainLength(variable->scope()); |
1887 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 1888 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
1888 // Perform an initialization check for legacy const variables. | 1889 // Perform an initialization check for legacy const variables. |
1889 Operator* op = | 1890 const Operator* op = |
1890 javascript()->LoadContext(depth, variable->index(), false); | 1891 javascript()->LoadContext(depth, variable->index(), false); |
1891 Node* current = NewNode(op, current_context()); | 1892 Node* current = NewNode(op, current_context()); |
1892 value = BuildHoleCheckSilent(current, value, current); | 1893 value = BuildHoleCheckSilent(current, value, current); |
1893 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { | 1894 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { |
1894 // Non-initializing assignments to legacy const is ignored. | 1895 // Non-initializing assignments to legacy const is ignored. |
1895 return value; | 1896 return value; |
1896 } else if (mode == LET && op != Token::INIT_LET) { | 1897 } else if (mode == LET && op != Token::INIT_LET) { |
1897 // Perform an initialization check for let declared variables. | 1898 // Perform an initialization check for let declared variables. |
1898 Operator* op = | 1899 const Operator* op = |
1899 javascript()->LoadContext(depth, variable->index(), false); | 1900 javascript()->LoadContext(depth, variable->index(), false); |
1900 Node* current = NewNode(op, current_context()); | 1901 Node* current = NewNode(op, current_context()); |
1901 value = BuildHoleCheckThrow(current, variable, value); | 1902 value = BuildHoleCheckThrow(current, variable, value); |
1902 } else if (mode == CONST && op != Token::INIT_CONST) { | 1903 } else if (mode == CONST && op != Token::INIT_CONST) { |
1903 // All assignments to const variables are early errors. | 1904 // All assignments to const variables are early errors. |
1904 UNREACHABLE(); | 1905 UNREACHABLE(); |
1905 } | 1906 } |
1906 Operator* op = javascript()->StoreContext(depth, variable->index()); | 1907 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
1907 return NewNode(op, current_context(), value); | 1908 return NewNode(op, current_context(), value); |
1908 } | 1909 } |
1909 case Variable::LOOKUP: { | 1910 case Variable::LOOKUP: { |
1910 // Dynamic lookup of context variable (anywhere in the chain). | 1911 // Dynamic lookup of context variable (anywhere in the chain). |
1911 Node* name = jsgraph()->Constant(variable->name()); | 1912 Node* name = jsgraph()->Constant(variable->name()); |
1912 Node* strict = jsgraph()->Constant(strict_mode()); | 1913 Node* strict = jsgraph()->Constant(strict_mode()); |
1913 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for | 1914 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for |
1914 // initializations of const declarations. | 1915 // initializations of const declarations. |
1915 Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); | 1916 const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); |
1916 return NewNode(op, value, current_context(), name, strict); | 1917 return NewNode(op, value, current_context(), name, strict); |
1917 } | 1918 } |
1918 } | 1919 } |
1919 UNREACHABLE(); | 1920 UNREACHABLE(); |
1920 return NULL; | 1921 return NULL; |
1921 } | 1922 } |
1922 | 1923 |
1923 | 1924 |
1924 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { | 1925 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { |
1925 // TODO(sigurds) Use simplified load here once it is ready. | 1926 // TODO(sigurds) Use simplified load here once it is ready. |
1926 MachineOperatorBuilder machine(zone()); | 1927 MachineOperatorBuilder machine(zone()); |
1927 Node* field_load = NewNode(machine.Load(kMachAnyTagged), object, | 1928 Node* field_load = NewNode(machine.Load(kMachAnyTagged), object, |
1928 jsgraph_->Int32Constant(offset - kHeapObjectTag)); | 1929 jsgraph_->Int32Constant(offset - kHeapObjectTag)); |
1929 return field_load; | 1930 return field_load; |
1930 } | 1931 } |
1931 | 1932 |
1932 | 1933 |
1933 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { | 1934 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { |
1934 Node* global = BuildLoadGlobalObject(); | 1935 Node* global = BuildLoadGlobalObject(); |
1935 Node* builtins = | 1936 Node* builtins = |
1936 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); | 1937 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); |
1937 return builtins; | 1938 return builtins; |
1938 } | 1939 } |
1939 | 1940 |
1940 | 1941 |
1941 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 1942 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
1942 Node* context = GetFunctionContext(); | 1943 Node* context = GetFunctionContext(); |
1943 Operator* load_op = | 1944 const Operator* load_op = |
1944 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); | 1945 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); |
1945 return NewNode(load_op, context); | 1946 return NewNode(load_op, context); |
1946 } | 1947 } |
1947 | 1948 |
1948 | 1949 |
1949 Node* AstGraphBuilder::BuildToBoolean(Node* value) { | 1950 Node* AstGraphBuilder::BuildToBoolean(Node* value) { |
1950 // TODO(mstarzinger): Possible optimization is to NOP for boolean values. | 1951 // TODO(mstarzinger): Possible optimization is to NOP for boolean values. |
1951 return NewNode(javascript()->ToBoolean(), value); | 1952 return NewNode(javascript()->ToBoolean(), value); |
1952 } | 1953 } |
1953 | 1954 |
1954 | 1955 |
1955 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) { | 1956 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) { |
1956 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. | 1957 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. |
1957 Node* variable_name = jsgraph()->Constant(variable->name()); | 1958 Node* variable_name = jsgraph()->Constant(variable->name()); |
1958 Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); | 1959 const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); |
1959 return NewNode(op, variable_name); | 1960 return NewNode(op, variable_name); |
1960 } | 1961 } |
1961 | 1962 |
1962 | 1963 |
1963 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { | 1964 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { |
1964 Operator* js_op; | 1965 const Operator* js_op; |
1965 switch (op) { | 1966 switch (op) { |
1966 case Token::BIT_OR: | 1967 case Token::BIT_OR: |
1967 js_op = javascript()->BitwiseOr(); | 1968 js_op = javascript()->BitwiseOr(); |
1968 break; | 1969 break; |
1969 case Token::BIT_AND: | 1970 case Token::BIT_AND: |
1970 js_op = javascript()->BitwiseAnd(); | 1971 js_op = javascript()->BitwiseAnd(); |
1971 break; | 1972 break; |
1972 case Token::BIT_XOR: | 1973 case Token::BIT_XOR: |
1973 js_op = javascript()->BitwiseXor(); | 1974 js_op = javascript()->BitwiseXor(); |
1974 break; | 1975 break; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2012 DCHECK(node->InputAt(frame_state_index)->op()->opcode() == IrOpcode::kDead); | 2013 DCHECK(node->InputAt(frame_state_index)->op()->opcode() == IrOpcode::kDead); |
2013 | 2014 |
2014 Node* frame_state_node = environment()->Checkpoint(ast_id, combine); | 2015 Node* frame_state_node = environment()->Checkpoint(ast_id, combine); |
2015 node->ReplaceInput(frame_state_index, frame_state_node); | 2016 node->ReplaceInput(frame_state_index, frame_state_node); |
2016 } | 2017 } |
2017 } | 2018 } |
2018 | 2019 |
2019 } | 2020 } |
2020 } | 2021 } |
2021 } // namespace v8::internal::compiler | 2022 } // namespace v8::internal::compiler |
OLD | NEW |