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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 UpdateControlDependencyToLeaveFunction(control); | 126 UpdateControlDependencyToLeaveFunction(control); | 
| 127 | 127 | 
| 128 // Finish the basic structure of the graph. | 128 // Finish the basic structure of the graph. | 
| 129 environment()->UpdateControlDependency(exit_control()); | 129 environment()->UpdateControlDependency(exit_control()); | 
| 130 graph()->SetEnd(NewNode(common()->End())); | 130 graph()->SetEnd(NewNode(common()->End())); | 
| 131 | 131 | 
| 132 return true; | 132 return true; | 
| 133 } | 133 } | 
| 134 | 134 | 
| 135 | 135 | 
| 136 // Helper class to create a new context for block scopes. This also implicitly | |
| 137 // pushes a ContextScope and visits declarations for the newly created context. | |
| 138 class AstGraphBuilder::BlockContextScope FINAL : public ContextScope { | |
| 139 public: | |
| 140 BlockContextScope(AstGraphBuilder* owner, Scope* scope) | |
| 141 : ContextScope(owner, scope, CreateBlockContext(owner, scope)) { | |
| 142 owner->VisitDeclarations(scope->declarations()); | |
| 143 } | |
| 144 | |
| 145 private: | |
| 146 static Node* CreateBlockContext(AstGraphBuilder* owner, Scope* scope) { | |
| 147 const Operator* op = owner->javascript()->CreateBlockContext(); | |
| 148 Node* scope_info = owner->jsgraph()->Constant(scope->GetScopeInfo()); | |
| 149 return owner->NewNode(op, scope_info, owner->GetFunctionClosure()); | |
| 150 } | |
| 151 }; | |
| 152 | |
| 153 | |
| 136 // Left-hand side can only be a property, a global or a variable slot. | 154 // Left-hand side can only be a property, a global or a variable slot. | 
| 137 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 155 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 
| 138 | 156 | 
| 139 | 157 | 
| 140 // Determine the left-hand side kind of an assignment. | 158 // Determine the left-hand side kind of an assignment. | 
| 141 static LhsKind DetermineLhsKind(Expression* expr) { | 159 static LhsKind DetermineLhsKind(Expression* expr) { | 
| 142 Property* property = expr->AsProperty(); | 160 Property* property = expr->AsProperty(); | 
| 143 DCHECK(expr->IsValidReferenceExpression()); | 161 DCHECK(expr->IsValidReferenceExpression()); | 
| 144 LhsKind lhs_kind = | 162 LhsKind lhs_kind = | 
| 145 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) | 163 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) | 
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 313 | 331 | 
| 314 | 332 | 
| 315 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { | 333 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { | 
| 316 if (expr == NULL) { | 334 if (expr == NULL) { | 
| 317 return environment()->Push(jsgraph()->NullConstant()); | 335 return environment()->Push(jsgraph()->NullConstant()); | 
| 318 } | 336 } | 
| 319 VisitForValue(expr); | 337 VisitForValue(expr); | 
| 320 } | 338 } | 
| 321 | 339 | 
| 322 | 340 | 
| 341 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { | |
| 342 if (expr == NULL) { | |
| 343 return environment()->Push(jsgraph()->TheHoleConstant()); | |
| 
 
arv (Not doing code reviews)
2015/01/14 15:49:10
I could also have the parser use TheHole instead o
 
Michael Starzinger
2015/01/14 16:02:19
Hmm, I don't have an opinion either way. On the on
 
rossberg
2015/01/15 15:31:19
Using the hole here would be confusing levels. We
 
Michael Starzinger
2015/01/16 09:43:54
Acknowledged.
 
 | |
| 344 } | |
| 345 VisitForValue(expr); | |
| 346 } | |
| 347 | |
| 348 | |
| 323 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { | 349 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { | 
| 324 for (int i = 0; i < exprs->length(); ++i) { | 350 for (int i = 0; i < exprs->length(); ++i) { | 
| 325 VisitForValue(exprs->at(i)); | 351 VisitForValue(exprs->at(i)); | 
| 326 } | 352 } | 
| 327 } | 353 } | 
| 328 | 354 | 
| 329 | 355 | 
| 330 void AstGraphBuilder::VisitForValue(Expression* expr) { | 356 void AstGraphBuilder::VisitForValue(Expression* expr) { | 
| 331 AstValueContext for_value(this); | 357 AstValueContext for_value(this); | 
| 332 if (!CheckStackOverflow()) { | 358 if (!CheckStackOverflow()) { | 
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 | 488 | 
| 463 | 489 | 
| 464 void AstGraphBuilder::VisitBlock(Block* stmt) { | 490 void AstGraphBuilder::VisitBlock(Block* stmt) { | 
| 465 BlockBuilder block(this); | 491 BlockBuilder block(this); | 
| 466 BreakableScope scope(this, stmt, &block, 0); | 492 BreakableScope scope(this, stmt, &block, 0); | 
| 467 if (stmt->labels() != NULL) block.BeginBlock(); | 493 if (stmt->labels() != NULL) block.BeginBlock(); | 
| 468 if (stmt->scope() == NULL) { | 494 if (stmt->scope() == NULL) { | 
| 469 // Visit statements in the same scope, no declarations. | 495 // Visit statements in the same scope, no declarations. | 
| 470 VisitStatements(stmt->statements()); | 496 VisitStatements(stmt->statements()); | 
| 471 } else { | 497 } else { | 
| 472 const Operator* op = javascript()->CreateBlockContext(); | |
| 473 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo()); | |
| 474 Node* context = NewNode(op, scope_info, GetFunctionClosure()); | |
| 475 ContextScope scope(this, stmt->scope(), context); | |
| 476 | |
| 477 // Visit declarations and statements in a block scope. | 498 // Visit declarations and statements in a block scope. | 
| 478 VisitDeclarations(stmt->scope()->declarations()); | 499 BlockContextScope scope(this, stmt->scope()); | 
| 479 VisitStatements(stmt->statements()); | 500 VisitStatements(stmt->statements()); | 
| 480 } | 501 } | 
| 481 if (stmt->labels() != NULL) block.EndBlock(); | 502 if (stmt->labels() != NULL) block.EndBlock(); | 
| 482 } | 503 } | 
| 483 | 504 | 
| 484 | 505 | 
| 485 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 506 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 
| 486 UNREACHABLE(); | 507 UNREACHABLE(); | 
| 487 } | 508 } | 
| 488 | 509 | 
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 // Create node to instantiate a new closure. | 848 // Create node to instantiate a new closure. | 
| 828 Node* info = jsgraph()->Constant(shared_info); | 849 Node* info = jsgraph()->Constant(shared_info); | 
| 829 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); | 850 Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure()); | 
| 830 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); | 851 const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3); | 
| 831 Node* value = NewNode(op, context, info, pretenure); | 852 Node* value = NewNode(op, context, info, pretenure); | 
| 832 ast_context()->ProduceValue(value); | 853 ast_context()->ProduceValue(value); | 
| 833 } | 854 } | 
| 834 | 855 | 
| 835 | 856 | 
| 836 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { | 857 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { | 
| 837 UNREACHABLE(); | 858 if (expr->scope() == NULL) { | 
| 859 // Visit class literal in the same scope, no declarations. | |
| 860 VisitClassLiteralContents(expr); | |
| 861 } else { | |
| 862 // Visit declarations and class literal in a block scope. | |
| 863 BlockContextScope scope(this, expr->scope()); | |
| 864 VisitClassLiteralContents(expr); | |
| 865 } | |
| 838 } | 866 } | 
| 839 | 867 | 
| 840 | 868 | 
| 869 void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { | |
| 870 Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name()) | |
| 871 : jsgraph()->UndefinedConstant(); | |
| 872 | |
| 873 // The class name is expected on the operand stack. | |
| 874 environment()->Push(class_name); | |
| 875 VisitForValueOrTheHole(expr->extends()); | |
| 876 VisitForValue(expr->constructor()); | |
| 877 | |
| 878 // Create node to instantiate a new class. | |
| 879 Node* constructor = environment()->Pop(); | |
| 880 Node* extends = environment()->Pop(); | |
| 881 Node* name = environment()->Pop(); | |
| 882 Node* script = jsgraph()->Constant(info()->script()); | |
| 883 Node* start = jsgraph()->Constant(expr->start_position()); | |
| 884 Node* end = jsgraph()->Constant(expr->end_position()); | |
| 885 const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 6); | |
| 886 Node* literal = NewNode(opc, name, extends, constructor, script, start, end); | |
| 887 | |
| 888 // The prototype is ensured to exist by Runtime_DefineClass. No access check | |
| 889 // is needed here since the constructor is created by the class literal. | |
| 890 Node* proto = | |
| 891 BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset); | |
| 892 | |
| 893 // The class literal and the prototype are both expected on the operand stack | |
| 894 // during evaluation of the method values. | |
| 895 environment()->Push(literal); | |
| 896 environment()->Push(proto); | |
| 897 | |
| 898 // Create nodes to store method values into the literal. | |
| 899 for (int i = 0; i < expr->properties()->length(); i++) { | |
| 900 ObjectLiteral::Property* property = expr->properties()->at(i); | |
| 901 environment()->Push(property->is_static() ? literal : proto); | |
| 902 | |
| 903 VisitForValue(property->key()); | |
| 904 VisitForValue(property->value()); | |
| 905 Node* value = environment()->Pop(); | |
| 906 Node* key = environment()->Pop(); | |
| 907 Node* receiver = environment()->Pop(); | |
| 908 switch (property->kind()) { | |
| 909 case ObjectLiteral::Property::CONSTANT: | |
| 910 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | |
| 911 case ObjectLiteral::Property::COMPUTED: | |
| 912 case ObjectLiteral::Property::PROTOTYPE: { | |
| 913 const Operator* op = | |
| 914 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3); | |
| 915 NewNode(op, receiver, key, value); | |
| 916 break; | |
| 917 } | |
| 918 case ObjectLiteral::Property::GETTER: { | |
| 919 const Operator* op = | |
| 920 javascript()->CallRuntime(Runtime::kDefineClassGetter, 3); | |
| 921 NewNode(op, receiver, key, value); | |
| 922 break; | |
| 923 } | |
| 924 case ObjectLiteral::Property::SETTER: { | |
| 925 const Operator* op = | |
| 926 javascript()->CallRuntime(Runtime::kDefineClassSetter, 3); | |
| 927 NewNode(op, receiver, key, value); | |
| 928 break; | |
| 929 } | |
| 930 } | |
| 931 | |
| 932 // TODO(mstarzinger): This is temporary to make "super" work and replicates | |
| 933 // the existing FullCodeGenerator::NeedsHomeObject predicate. | |
| 934 if (FunctionLiteral::NeedsHomeObject(property->value())) { | |
| 935 Unique<Name> name = | |
| 936 MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 937 NewNode(javascript()->StoreNamed(strict_mode(), name), value, receiver); | |
| 938 } | |
| 939 } | |
| 940 | |
| 941 // Transform both the class literal and the prototype to fast properties. | |
| 942 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); | |
| 943 NewNode(op, environment()->Pop()); // prototype | |
| 944 NewNode(op, environment()->Pop()); // literal | |
| 945 | |
| 946 // Assign to class variable. | |
| 947 if (expr->scope() != NULL) { | |
| 948 DCHECK_NOT_NULL(expr->class_variable_proxy()); | |
| 949 Variable* var = expr->class_variable_proxy()->var(); | |
| 950 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); | |
| 951 } | |
| 952 | |
| 953 ast_context()->ProduceValue(literal); | |
| 954 } | |
| 955 | |
| 956 | |
| 841 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 957 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 
| 842 UNREACHABLE(); | 958 UNREACHABLE(); | 
| 843 } | 959 } | 
| 844 | 960 | 
| 845 | 961 | 
| 846 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 962 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 
| 847 IfBuilder compare_if(this); | 963 IfBuilder compare_if(this); | 
| 848 VisitForTest(expr->condition()); | 964 VisitForTest(expr->condition()); | 
| 849 Node* condition = environment()->Pop(); | 965 Node* condition = environment()->Pop(); | 
| 850 compare_if.If(condition); | 966 compare_if.If(condition); | 
| (...skipping 1386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 | 2353 | 
| 2238 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2354 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 
| 2239 IterationStatement* stmt) { | 2355 IterationStatement* stmt) { | 
| 2240 if (loop_assignment_analysis_ == NULL) return NULL; | 2356 if (loop_assignment_analysis_ == NULL) return NULL; | 
| 2241 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2357 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 
| 2242 } | 2358 } | 
| 2243 | 2359 | 
| 2244 } // namespace compiler | 2360 } // namespace compiler | 
| 2245 } // namespace internal | 2361 } // namespace internal | 
| 2246 } // namespace v8 | 2362 } // namespace v8 | 
| OLD | NEW |