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/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 313 |
314 | 314 |
315 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { | 315 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { |
316 if (expr == NULL) { | 316 if (expr == NULL) { |
317 return environment()->Push(jsgraph()->NullConstant()); | 317 return environment()->Push(jsgraph()->NullConstant()); |
318 } | 318 } |
319 VisitForValue(expr); | 319 VisitForValue(expr); |
320 } | 320 } |
321 | 321 |
322 | 322 |
| 323 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { |
| 324 if (expr == NULL) { |
| 325 return environment()->Push(jsgraph()->TheHoleConstant()); |
| 326 } |
| 327 VisitForValue(expr); |
| 328 } |
| 329 |
| 330 |
323 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { | 331 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { |
324 for (int i = 0; i < exprs->length(); ++i) { | 332 for (int i = 0; i < exprs->length(); ++i) { |
325 VisitForValue(exprs->at(i)); | 333 VisitForValue(exprs->at(i)); |
326 } | 334 } |
327 } | 335 } |
328 | 336 |
329 | 337 |
330 void AstGraphBuilder::VisitForValue(Expression* expr) { | 338 void AstGraphBuilder::VisitForValue(Expression* expr) { |
331 AstValueContext for_value(this); | 339 AstValueContext for_value(this); |
332 if (!CheckStackOverflow()) { | 340 if (!CheckStackOverflow()) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 | 470 |
463 | 471 |
464 void AstGraphBuilder::VisitBlock(Block* stmt) { | 472 void AstGraphBuilder::VisitBlock(Block* stmt) { |
465 BlockBuilder block(this); | 473 BlockBuilder block(this); |
466 BreakableScope scope(this, stmt, &block, 0); | 474 BreakableScope scope(this, stmt, &block, 0); |
467 if (stmt->labels() != NULL) block.BeginBlock(); | 475 if (stmt->labels() != NULL) block.BeginBlock(); |
468 if (stmt->scope() == NULL) { | 476 if (stmt->scope() == NULL) { |
469 // Visit statements in the same scope, no declarations. | 477 // Visit statements in the same scope, no declarations. |
470 VisitStatements(stmt->statements()); | 478 VisitStatements(stmt->statements()); |
471 } else { | 479 } else { |
472 const Operator* op = javascript()->CreateBlockContext(); | 480 // Visit declarations and statements in a block scope. |
473 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo()); | 481 Node* context = BuildLocalBlockContext(stmt->scope()); |
474 Node* context = NewNode(op, scope_info, GetFunctionClosure()); | |
475 ContextScope scope(this, stmt->scope(), context); | 482 ContextScope scope(this, stmt->scope(), context); |
476 | |
477 // Visit declarations and statements in a block scope. | |
478 VisitDeclarations(stmt->scope()->declarations()); | 483 VisitDeclarations(stmt->scope()->declarations()); |
479 VisitStatements(stmt->statements()); | 484 VisitStatements(stmt->statements()); |
480 } | 485 } |
481 if (stmt->labels() != NULL) block.EndBlock(); | 486 if (stmt->labels() != NULL) block.EndBlock(); |
482 } | 487 } |
483 | 488 |
484 | 489 |
485 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 490 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
486 UNREACHABLE(); | 491 UNREACHABLE(); |
487 } | 492 } |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 // Create node to instantiate a new closure. | 840 // Create node to instantiate a new closure. |
836 Node* info = jsgraph()->Constant(shared_info); | 841 Node* info = jsgraph()->Constant(shared_info); |
837 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); | 842 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); |
838 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); | 843 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); |
839 Node* value = NewNode(op, context, info, pretenure); | 844 Node* value = NewNode(op, context, info, pretenure); |
840 ast_context()->ProduceValue(value); | 845 ast_context()->ProduceValue(value); |
841 } | 846 } |
842 | 847 |
843 | 848 |
844 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { | 849 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { |
845 UNREACHABLE(); | 850 if (expr->scope() == NULL) { |
| 851 // Visit class literal in the same scope, no declarations. |
| 852 VisitClassLiteralContents(expr); |
| 853 } else { |
| 854 // Visit declarations and class literal in a block scope. |
| 855 Node* context = BuildLocalBlockContext(expr->scope()); |
| 856 ContextScope scope(this, expr->scope(), context); |
| 857 VisitDeclarations(expr->scope()->declarations()); |
| 858 VisitClassLiteralContents(expr); |
| 859 } |
846 } | 860 } |
847 | 861 |
848 | 862 |
| 863 void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { |
| 864 Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name()) |
| 865 : jsgraph()->UndefinedConstant(); |
| 866 |
| 867 // The class name is expected on the operand stack. |
| 868 environment()->Push(class_name); |
| 869 VisitForValueOrTheHole(expr->extends()); |
| 870 VisitForValue(expr->constructor()); |
| 871 |
| 872 // Create node to instantiate a new class. |
| 873 Node* constructor = environment()->Pop(); |
| 874 Node* extends = environment()->Pop(); |
| 875 Node* name = environment()->Pop(); |
| 876 Node* script = jsgraph()->Constant(info()->script()); |
| 877 Node* start = jsgraph()->Constant(expr->start_position()); |
| 878 Node* end = jsgraph()->Constant(expr->end_position()); |
| 879 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 6); |
| 880 Node* literal = NewNode(opc, name, extends, constructor, script, start, end); |
| 881 |
| 882 // The prototype is ensured to exist by Runtime_DefineClass. No access check |
| 883 // is needed here since the constructor is created by the class literal. |
| 884 Node* proto = |
| 885 BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset); |
| 886 |
| 887 // The class literal and the prototype are both expected on the operand stack |
| 888 // during evaluation of the method values. |
| 889 environment()->Push(literal); |
| 890 environment()->Push(proto); |
| 891 |
| 892 // Create nodes to store method values into the literal. |
| 893 for (int i = 0; i < expr->properties()->length(); i++) { |
| 894 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 895 environment()->Push(property->is_static() ? literal : proto); |
| 896 |
| 897 VisitForValue(property->key()); |
| 898 VisitForValue(property->value()); |
| 899 Node* value = environment()->Pop(); |
| 900 Node* key = environment()->Pop(); |
| 901 Node* receiver = environment()->Pop(); |
| 902 switch (property->kind()) { |
| 903 case ObjectLiteral::Property::CONSTANT: |
| 904 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 905 UNREACHABLE(); |
| 906 case ObjectLiteral::Property::COMPUTED: |
| 907 case ObjectLiteral::Property::PROTOTYPE: { |
| 908 const Operator* op = |
| 909 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3); |
| 910 NewNode(op, receiver, key, value); |
| 911 break; |
| 912 } |
| 913 case ObjectLiteral::Property::GETTER: { |
| 914 const Operator* op = javascript()->CallRuntime( |
| 915 Runtime::kDefineGetterPropertyUnchecked, 3); |
| 916 NewNode(op, receiver, key, value); |
| 917 break; |
| 918 } |
| 919 case ObjectLiteral::Property::SETTER: { |
| 920 const Operator* op = javascript()->CallRuntime( |
| 921 Runtime::kDefineSetterPropertyUnchecked, 3); |
| 922 NewNode(op, receiver, key, value); |
| 923 break; |
| 924 } |
| 925 } |
| 926 |
| 927 // TODO(mstarzinger): This is temporary to make "super" work and replicates |
| 928 // the existing FullCodeGenerator::NeedsHomeObject predicate. |
| 929 if (FunctionLiteral::NeedsHomeObject(property->value())) { |
| 930 Unique<Name> name = |
| 931 MakeUnique(isolate()->factory()->home_object_symbol()); |
| 932 NewNode(javascript()->StoreNamed(strict_mode(), name), value, receiver); |
| 933 } |
| 934 } |
| 935 |
| 936 // Transform both the class literal and the prototype to fast properties. |
| 937 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); |
| 938 NewNode(op, environment()->Pop()); // prototype |
| 939 NewNode(op, environment()->Pop()); // literal |
| 940 |
| 941 // Assign to class variable. |
| 942 if (expr->scope() != NULL) { |
| 943 DCHECK_NOT_NULL(expr->class_variable_proxy()); |
| 944 Variable* var = expr->class_variable_proxy()->var(); |
| 945 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); |
| 946 } |
| 947 |
| 948 ast_context()->ProduceValue(literal); |
| 949 } |
| 950 |
| 951 |
849 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 952 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
850 UNREACHABLE(); | 953 UNREACHABLE(); |
851 } | 954 } |
852 | 955 |
853 | 956 |
854 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 957 void AstGraphBuilder::VisitConditional(Conditional* expr) { |
855 IfBuilder compare_if(this); | 958 IfBuilder compare_if(this); |
856 VisitForTest(expr->condition()); | 959 VisitForTest(expr->condition()); |
857 Node* condition = environment()->Pop(); | 960 Node* condition = environment()->Pop(); |
858 compare_if.If(condition); | 961 compare_if.If(condition); |
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1822 // Context variable (at bottom of the context chain). | 1925 // Context variable (at bottom of the context chain). |
1823 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); | 1926 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); |
1824 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1927 const Operator* op = javascript()->StoreContext(0, variable->index()); |
1825 NewNode(op, local_context, parameter); | 1928 NewNode(op, local_context, parameter); |
1826 } | 1929 } |
1827 | 1930 |
1828 return local_context; | 1931 return local_context; |
1829 } | 1932 } |
1830 | 1933 |
1831 | 1934 |
| 1935 Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) { |
| 1936 Node* closure = GetFunctionClosure(); |
| 1937 |
| 1938 // Allocate a new local context. |
| 1939 const Operator* op = javascript()->CreateBlockContext(); |
| 1940 Node* scope_info = jsgraph()->Constant(scope->GetScopeInfo()); |
| 1941 Node* local_context = NewNode(op, scope_info, closure); |
| 1942 |
| 1943 return local_context; |
| 1944 } |
| 1945 |
| 1946 |
1832 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { | 1947 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
1833 if (arguments == NULL) return NULL; | 1948 if (arguments == NULL) return NULL; |
1834 | 1949 |
1835 // Allocate and initialize a new arguments object. | 1950 // Allocate and initialize a new arguments object. |
1836 Node* callee = GetFunctionClosure(); | 1951 Node* callee = GetFunctionClosure(); |
1837 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); | 1952 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); |
1838 Node* object = NewNode(op, callee); | 1953 Node* object = NewNode(op, callee); |
1839 | 1954 |
1840 // Assign the object to the arguments variable. | 1955 // Assign the object to the arguments variable. |
1841 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 1956 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2242 | 2357 |
2243 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2358 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
2244 IterationStatement* stmt) { | 2359 IterationStatement* stmt) { |
2245 if (loop_assignment_analysis_ == NULL) return NULL; | 2360 if (loop_assignment_analysis_ == NULL) return NULL; |
2246 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2361 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
2247 } | 2362 } |
2248 | 2363 |
2249 } // namespace compiler | 2364 } // namespace compiler |
2250 } // namespace internal | 2365 } // namespace internal |
2251 } // namespace v8 | 2366 } // namespace v8 |
OLD | NEW |