Chromium Code Reviews| 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 // Create node to instantiate a new closure. | 832 // Create node to instantiate a new closure. |
| 828 Node* info = jsgraph()->Constant(shared_info); | 833 Node* info = jsgraph()->Constant(shared_info); |
| 829 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); | 834 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); |
| 830 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); | 835 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); |
| 831 Node* value = NewNode(op, context, info, pretenure); | 836 Node* value = NewNode(op, context, info, pretenure); |
| 832 ast_context()->ProduceValue(value); | 837 ast_context()->ProduceValue(value); |
| 833 } | 838 } |
| 834 | 839 |
| 835 | 840 |
| 836 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { | 841 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { |
| 837 UNREACHABLE(); | 842 if (expr->scope() == NULL) { |
| 843 // Visit class literal in the same scope, no declarations. | |
| 844 VisitClassLiteralContents(expr); | |
| 845 } else { | |
| 846 // Visit declarations and class literal in a block scope. | |
| 847 Node* context = BuildLocalBlockContext(expr->scope()); | |
| 848 ContextScope scope(this, expr->scope(), context); | |
| 849 VisitDeclarations(expr->scope()->declarations()); | |
| 850 VisitClassLiteralContents(expr); | |
| 851 } | |
| 838 } | 852 } |
| 839 | 853 |
| 840 | 854 |
| 855 void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { | |
| 856 Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name()) | |
| 857 : jsgraph()->UndefinedConstant(); | |
| 858 | |
| 859 // The class name is expected on the operand stack. | |
| 860 environment()->Push(class_name); | |
| 861 VisitForValueOrTheHole(expr->extends()); | |
| 862 VisitForValue(expr->constructor()); | |
| 863 | |
| 864 // Create node to instantiate a new class. | |
| 865 Node* constructor = environment()->Pop(); | |
| 866 Node* extends = environment()->Pop(); | |
| 867 Node* name = environment()->Pop(); | |
| 868 Node* script = jsgraph()->Constant(info()->script()); | |
| 869 Node* start = jsgraph()->Constant(expr->start_position()); | |
| 870 Node* end = jsgraph()->Constant(expr->end_position()); | |
| 871 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 6); | |
| 872 Node* literal = NewNode(opc, name, extends, constructor, script, start, end); | |
| 873 | |
| 874 // The prototype is ensured to exist by Runtime_DefineClass. No access check | |
| 875 // is needed here since the constructor is created by the class literal. | |
| 876 Node* proto = | |
| 877 BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset); | |
| 878 | |
| 879 // The class literal and the prototype are both expected on the operand stack | |
| 880 // during evaluation of the method values. | |
| 881 environment()->Push(literal); | |
| 882 environment()->Push(proto); | |
| 883 | |
| 884 // Create nodes to store method values into the literal. | |
| 885 for (int i = 0; i < expr->properties()->length(); i++) { | |
| 886 ObjectLiteral::Property* property = expr->properties()->at(i); | |
| 887 environment()->Push(property->is_static() ? literal : proto); | |
| 888 | |
| 889 VisitForValue(property->key()); | |
| 890 VisitForValue(property->value()); | |
| 891 Node* value = environment()->Pop(); | |
| 892 Node* key = environment()->Pop(); | |
| 893 Node* receiver = environment()->Pop(); | |
| 894 switch (property->kind()) { | |
| 895 case ObjectLiteral::Property::CONSTANT: | |
| 896 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | |
| 897 case ObjectLiteral::Property::COMPUTED: | |
| 898 case ObjectLiteral::Property::PROTOTYPE: { | |
|
rossberg
2015/01/15 15:31:19
It seems to me that none but MATERIALIZED_LITERAL
arv (Not doing code reviews)
2015/01/15 16:12:24
I believe PROTOTYPE can happen too
class C {
__
rossberg
2015/01/15 16:35:11
That is just considered a regular method definitio
arv (Not doing code reviews)
2015/01/15 16:51:02
The AST only checks the value of the property name
Michael Starzinger
2015/01/16 09:43:54
Done. Made CONSTANT and MATERIALIZED_LITERAL unrea
arv (Not doing code reviews)
2015/01/16 14:42:07
I'll take care of this in a follow up CL
| |
| 899 const Operator* op = | |
| 900 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3); | |
| 901 NewNode(op, receiver, key, value); | |
| 902 break; | |
| 903 } | |
| 904 case ObjectLiteral::Property::GETTER: { | |
| 905 const Operator* op = | |
| 906 javascript()->CallRuntime(Runtime::kDefineClassGetter, 3); | |
| 907 NewNode(op, receiver, key, value); | |
| 908 break; | |
| 909 } | |
| 910 case ObjectLiteral::Property::SETTER: { | |
| 911 const Operator* op = | |
| 912 javascript()->CallRuntime(Runtime::kDefineClassSetter, 3); | |
| 913 NewNode(op, receiver, key, value); | |
| 914 break; | |
| 915 } | |
| 916 } | |
| 917 | |
| 918 // TODO(mstarzinger): This is temporary to make "super" work and replicates | |
| 919 // the existing FullCodeGenerator::NeedsHomeObject predicate. | |
| 920 if (FunctionLiteral::NeedsHomeObject(property->value())) { | |
| 921 Unique<Name> name = | |
| 922 MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 923 NewNode(javascript()->StoreNamed(strict_mode(), name), value, receiver); | |
| 924 } | |
| 925 } | |
| 926 | |
| 927 // Transform both the class literal and the prototype to fast properties. | |
| 928 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); | |
| 929 NewNode(op, environment()->Pop()); // prototype | |
| 930 NewNode(op, environment()->Pop()); // literal | |
| 931 | |
| 932 // Assign to class variable. | |
| 933 if (expr->scope() != NULL) { | |
| 934 DCHECK_NOT_NULL(expr->class_variable_proxy()); | |
| 935 Variable* var = expr->class_variable_proxy()->var(); | |
| 936 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); | |
| 937 } | |
| 938 | |
| 939 ast_context()->ProduceValue(literal); | |
| 940 } | |
| 941 | |
| 942 | |
| 841 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 943 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 842 UNREACHABLE(); | 944 UNREACHABLE(); |
| 843 } | 945 } |
| 844 | 946 |
| 845 | 947 |
| 846 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 948 void AstGraphBuilder::VisitConditional(Conditional* expr) { |
| 847 IfBuilder compare_if(this); | 949 IfBuilder compare_if(this); |
| 848 VisitForTest(expr->condition()); | 950 VisitForTest(expr->condition()); |
| 849 Node* condition = environment()->Pop(); | 951 Node* condition = environment()->Pop(); |
| 850 compare_if.If(condition); | 952 compare_if.If(condition); |
| (...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1814 // Context variable (at bottom of the context chain). | 1916 // Context variable (at bottom of the context chain). |
| 1815 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); | 1917 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); |
| 1816 const Operator* op = javascript()->StoreContext(0, variable->index()); | 1918 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 1817 NewNode(op, local_context, parameter); | 1919 NewNode(op, local_context, parameter); |
| 1818 } | 1920 } |
| 1819 | 1921 |
| 1820 return local_context; | 1922 return local_context; |
| 1821 } | 1923 } |
| 1822 | 1924 |
| 1823 | 1925 |
| 1926 Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) { | |
| 1927 Node* closure = GetFunctionClosure(); | |
| 1928 | |
| 1929 // Allocate a new local context. | |
| 1930 const Operator* op = javascript()->CreateBlockContext(); | |
| 1931 Node* scope_info = jsgraph()->Constant(scope->GetScopeInfo()); | |
| 1932 Node* local_context = NewNode(op, scope_info, closure); | |
| 1933 | |
| 1934 return local_context; | |
| 1935 } | |
| 1936 | |
| 1937 | |
| 1824 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { | 1938 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
| 1825 if (arguments == NULL) return NULL; | 1939 if (arguments == NULL) return NULL; |
| 1826 | 1940 |
| 1827 // Allocate and initialize a new arguments object. | 1941 // Allocate and initialize a new arguments object. |
| 1828 Node* callee = GetFunctionClosure(); | 1942 Node* callee = GetFunctionClosure(); |
| 1829 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); | 1943 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); |
| 1830 Node* object = NewNode(op, callee); | 1944 Node* object = NewNode(op, callee); |
| 1831 | 1945 |
| 1832 // Assign the object to the arguments variable. | 1946 // Assign the object to the arguments variable. |
| 1833 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 1947 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 | 2351 |
| 2238 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2352 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
| 2239 IterationStatement* stmt) { | 2353 IterationStatement* stmt) { |
| 2240 if (loop_assignment_analysis_ == NULL) return NULL; | 2354 if (loop_assignment_analysis_ == NULL) return NULL; |
| 2241 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2355 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
| 2242 } | 2356 } |
| 2243 | 2357 |
| 2244 } // namespace compiler | 2358 } // namespace compiler |
| 2245 } // namespace internal | 2359 } // namespace internal |
| 2246 } // namespace v8 | 2360 } // namespace v8 |
| OLD | NEW |