Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 798873006: First simple implementation of class literals in TurboFan. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/pipeline.cc » ('j') | src/types.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698