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 |