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

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 1666943003: [interpreter] Support for ES6 class literals. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Incorporate mstarzinger's comments on patch set 1. Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index be2a558b86d0c9fe1abfd377b82c649bc55408d9..2346444d4b1e9c14da5dd6db4c824fc3a6c1a456 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -1226,9 +1226,145 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
- UNIMPLEMENTED();
+ if (expr->scope()->ContextLocalCount() > 0) {
+ VisitNewLocalBlockContext(expr->scope());
+ ContextScope scope(this, expr->scope());
+ VisitDeclarations(expr->scope()->declarations());
+ VisitClassLiteralContents(expr);
+ } else {
+ VisitDeclarations(expr->scope()->declarations());
+ VisitClassLiteralContents(expr);
+ }
+}
+
+void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
+ VisitClassLiteralForRuntimeDefinition(expr);
+ // The prototype is ensured to exist by Runtime_DefineClass in
+ // VisitClassForRuntimeDefinition. No access check is needed here
+ // since the constructor is created by the class literal.
+ register_allocator()->PrepareForConsecutiveAllocations(2);
+ Register literal = register_allocator()->NextConsecutiveRegister();
+ Register prototype = register_allocator()->NextConsecutiveRegister();
+ builder()->StoreAccumulatorInRegister(literal);
+ builder()->LoadPrototypeOrInitialMap();
rmcilroy 2016/02/04 14:56:41 nit - chain builders (in functions below too) ?
oth 2016/02/04 16:59:48 Done.
+ builder()->StoreAccumulatorInRegister(prototype);
+ VisitClassLiteralProperties(expr, literal, prototype);
+
+ // Set both the prototype and constructor to have fast properties, and also
+ // freeze them in strong mode.
rmcilroy 2016/02/04 14:56:41 Remove the comment about strong mode (we don't sup
oth 2016/02/04 16:59:48 Done.
+ builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2);
+ // Assign to class variable.
+ if (expr->class_variable_proxy() != nullptr) {
+ Variable* var = expr->class_variable_proxy()->var();
+ FeedbackVectorSlot slot = expr->NeedsProxySlot()
+ ? expr->ProxySlot()
+ : FeedbackVectorSlot::Invalid();
+ VisitVariableAssignment(var, slot);
+ }
+ execution_result()->SetResultInAccumulator();
+}
+
+void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
+ ClassLiteral* expr) {
+ AccumulatorResultScope result_scope(this);
+ register_allocator()->PrepareForConsecutiveAllocations(4);
+ Register extends = register_allocator()->NextConsecutiveRegister();
+ Register constructor = register_allocator()->NextConsecutiveRegister();
+ Register start_position = register_allocator()->NextConsecutiveRegister();
+ Register end_position = register_allocator()->NextConsecutiveRegister();
+ VisitForAccumulatorValueOrTheHole(expr->extends());
rmcilroy 2016/02/04 14:56:41 nit - newline above (bit of a wall of text otherwi
oth 2016/02/04 16:59:48 Done.
+ builder()->StoreAccumulatorInRegister(extends);
+ VisitForAccumulatorValue(expr->constructor());
+ builder()->StoreAccumulatorInRegister(constructor);
+ builder()->LoadLiteral(Smi::FromInt(expr->start_position()));
+ builder()->StoreAccumulatorInRegister(start_position);
+ builder()->LoadLiteral(Smi::FromInt(expr->end_position()));
+ builder()->StoreAccumulatorInRegister(end_position);
+ builder()->CallRuntime(Runtime::kDefineClass, extends, 4);
+ result_scope.SetResultInAccumulator();
+}
+
+void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
+ Register literal,
+ Register prototype) {
+ EffectResultScope result_scope(this);
rmcilroy 2016/02/04 14:56:41 Remove please (or replace with a RegisterAllocatio
oth 2016/02/04 16:59:48 Done.
+
+ register_allocator()->PrepareForConsecutiveAllocations(4);
+ Register receiver = register_allocator()->NextConsecutiveRegister();
+ Register key = register_allocator()->NextConsecutiveRegister();
+ Register value = register_allocator()->NextConsecutiveRegister();
+ Register attr = register_allocator()->NextConsecutiveRegister();
+
+ bool attr_assigned = false;
+ Register old_receiver = Register::invalid_value();
+
+ // Create nodes to store method values into the literal.
+ for (int i = 0; i < expr->properties()->length(); i++) {
+ ObjectLiteral::Property* property = expr->properties()->at(i);
+
+ // Set-up receiver.
+ Register new_receiver = property->is_static() ? literal : prototype;
+ if (new_receiver != old_receiver) {
+ builder()->MoveRegister(new_receiver, receiver);
+ old_receiver = new_receiver;
+ }
+
+ VisitForAccumulatorValue(property->key());
+ builder()->CastAccumulatorToName();
+ builder()->StoreAccumulatorInRegister(key);
+ // The static prototype property is read only. We handle the non computed
+ // property name case in the parser. Since this is the only case where we
+ // need to check for an own read only property we special case this so we do
+ // not need to do this for every property.
rmcilroy 2016/02/04 14:56:40 I think this comment might make more sense in Visi
oth 2016/02/04 16:59:48 It seems like the right place as it explains the p
rmcilroy 2016/02/04 17:37:06 Yeah sorry you are right, it belongs here.
+ if (property->is_static() && property->is_computed_name()) {
+ VisitClassLiteralStaticPrototypeWithComputedName(key);
+ }
+ VisitForAccumulatorValue(property->value());
+ builder()->StoreAccumulatorInRegister(value);
+
+ VisitSetHomeObject(value, receiver, property);
+
+ if ((property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER) &&
+ !attr_assigned) {
+ builder()
+ ->LoadLiteral(Smi::FromInt(DONT_ENUM))
+ .StoreAccumulatorInRegister(attr);
+ attr_assigned = true;
+ }
+
+ switch (property->kind()) {
+ case ObjectLiteral::Property::CONSTANT:
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+ case ObjectLiteral::Property::PROTOTYPE:
+ UNREACHABLE();
rmcilroy 2016/02/04 14:56:41 nit - comment on why this should be unreachable an
oth 2016/02/04 16:59:48 Done.
+ case ObjectLiteral::Property::COMPUTED: {
+ builder()->CallRuntime(Runtime::kDefineClassMethod, receiver, 3);
+ break;
+ }
+ case ObjectLiteral::Property::GETTER: {
+ builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
+ receiver, 4);
+ break;
+ }
+ case ObjectLiteral::Property::SETTER: {
+ builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
+ receiver, 4);
+ break;
+ }
+ }
+ }
}
+void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
+ Register key) {
+ BytecodeLabel done;
+ builder()->LoadLiteral(isolate()->factory()->prototype_string());
+ builder()->CompareOperation(Token::Value::EQ_STRICT, key, Strength::WEAK);
+ builder()->JumpIfFalse(&done);
+ builder()->CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0);
+ builder()->Bind(&done);
+}
void BytecodeGenerator::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) {
@@ -2518,6 +2654,13 @@ void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
Visit(expr);
}
+void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
+ if (expr == nullptr) {
+ builder()->LoadTheHole();
+ } else {
+ VisitForAccumulatorValue(expr);
+ }
+}
// Visits the expression |expr| and discards the result.
void BytecodeGenerator::VisitForEffect(Expression* expr) {

Powered by Google App Engine
This is Rietveld 408576698