From: arv@chromium.org Date: Wed, 29 Oct 2014 11:45:57 +0000 (+0000) Subject: Classes: Add super support in methods and accessors X-Git-Tag: upstream/4.7.83~6026 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b3f9ec76d1dd5ef16177c0389fb50390c43e254;p=platform%2Fupstream%2Fv8.git Classes: Add super support in methods and accessors This is done by installing the [[HomeObject]] on the method and the accessor functions. BUG=v8:3330 LOG=Y R=dslomov@chromium.org Review URL: https://codereview.chromium.org/683893002 Cr-Commit-Position: refs/heads/master@{#24976} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24976 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 76e6738..bdc68b1 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -2530,34 +2530,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { } __ push(scratch); VisitForStackValue(key); + VisitForStackValue(value); switch (property->kind()) { case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::PROTOTYPE: - VisitForStackValue(value); - __ mov(scratch, Operand(Smi::FromInt(NONE))); - __ push(scratch); - __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); + __ CallRuntime(Runtime::kDefineClassMethod, 3); break; case ObjectLiteral::Property::GETTER: - VisitForStackValue(value); - __ LoadRoot(scratch, Heap::kNullValueRootIndex); - __ push(scratch); - __ mov(scratch, Operand(Smi::FromInt(NONE))); - __ push(scratch); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassGetter, 3); break; case ObjectLiteral::Property::SETTER: - __ LoadRoot(scratch, Heap::kNullValueRootIndex); - __ push(scratch); - VisitForStackValue(value); - __ mov(scratch, Operand(Smi::FromInt(NONE))); - __ push(scratch); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassSetter, 3); break; default: diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index a318b61..792dc30 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -2202,34 +2202,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { } __ Push(scratch); VisitForStackValue(key); + VisitForStackValue(value); switch (property->kind()) { case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::PROTOTYPE: - VisitForStackValue(value); - __ Mov(scratch, Smi::FromInt(NONE)); - __ Push(scratch); - __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); + __ CallRuntime(Runtime::kDefineClassMethod, 3); break; case ObjectLiteral::Property::GETTER: - VisitForStackValue(value); - __ LoadRoot(scratch, Heap::kNullValueRootIndex); - __ push(scratch); - __ Mov(scratch, Smi::FromInt(NONE)); - __ Push(scratch); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassGetter, 3); break; case ObjectLiteral::Property::SETTER: - __ LoadRoot(scratch, Heap::kNullValueRootIndex); - __ push(scratch); - VisitForStackValue(value); - __ Mov(scratch, Smi::FromInt(NONE)); - __ Push(scratch); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassSetter, 3); break; default: diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index de08bd1..920d036 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -2444,29 +2444,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { __ push(Operand(esp, 0)); // prototype } VisitForStackValue(key); + VisitForStackValue(value); switch (property->kind()) { case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::PROTOTYPE: - VisitForStackValue(value); - __ push(Immediate(Smi::FromInt(NONE))); - __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); + __ CallRuntime(Runtime::kDefineClassMethod, 3); break; case ObjectLiteral::Property::GETTER: - VisitForStackValue(value); - __ push(Immediate(isolate()->factory()->null_value())); - __ push(Immediate(Smi::FromInt(NONE))); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassGetter, 3); break; case ObjectLiteral::Property::SETTER: - __ push(Immediate(isolate()->factory()->null_value())); - VisitForStackValue(value); - __ push(Immediate(Smi::FromInt(NONE))); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassSetter, 3); break; default: diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc index 15a08b0..cc4e09b 100644 --- a/src/runtime/runtime-classes.cc +++ b/src/runtime/runtime-classes.cc @@ -153,6 +153,84 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { } +RUNTIME_FUNCTION(Runtime_DefineClassMethod) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2); + + RETURN_FAILURE_ON_EXCEPTION( + isolate, JSObject::SetOwnPropertyIgnoreAttributes( + function, isolate->factory()->home_object_symbol(), object, + DONT_ENUM)); + + uint32_t index; + if (key->ToArrayIndex(&index)) { + RETURN_FAILURE_ON_EXCEPTION( + isolate, JSObject::SetOwnElement(object, index, function, STRICT)); + } + + Handle name; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, + Runtime::ToName(isolate, key)); + if (name->AsArrayIndex(&index)) { + RETURN_FAILURE_ON_EXCEPTION( + isolate, JSObject::SetOwnElement(object, index, function, STRICT)); + } else { + RETURN_FAILURE_ON_EXCEPTION( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes(object, name, function, NONE)); + } + return isolate->heap()->undefined_value(); +} + + +RUNTIME_FUNCTION(Runtime_DefineClassGetter) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2); + + Handle name; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, + Runtime::ToName(isolate, key)); + RETURN_FAILURE_ON_EXCEPTION( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + getter, isolate->factory()->home_object_symbol(), object, DONT_ENUM)); + + RETURN_FAILURE_ON_EXCEPTION( + isolate, + JSObject::DefineAccessor(object, name, getter, + isolate->factory()->null_value(), NONE)); + return isolate->heap()->undefined_value(); +} + + +RUNTIME_FUNCTION(Runtime_DefineClassSetter) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2); + + Handle name; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, + Runtime::ToName(isolate, key)); + RETURN_FAILURE_ON_EXCEPTION( + isolate, + JSObject::SetOwnPropertyIgnoreAttributes( + setter, isolate->factory()->home_object_symbol(), object, DONT_ENUM)); + RETURN_FAILURE_ON_EXCEPTION( + isolate, + JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), + setter, NONE)); + return isolate->heap()->undefined_value(); +} + + RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) { HandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 5217f62..599a024 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -188,6 +188,9 @@ namespace internal { F(ToMethod, 2, 1) \ F(HomeObjectSymbol, 0, 1) \ F(DefineClass, 6, 1) \ + F(DefineClassMethod, 3, 1) \ + F(DefineClassGetter, 3, 1) \ + F(DefineClassSetter, 3, 1) \ F(ClassGetSourceCode, 1, 1) \ F(ThrowNonMethodError, 0, 1) \ F(ThrowUnsupportedSuperError, 0, 1) \ diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index fe06fc7..085a55d 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -2443,29 +2443,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { __ Push(Operand(rsp, 0)); // prototype } VisitForStackValue(key); + VisitForStackValue(value); switch (property->kind()) { case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::PROTOTYPE: - VisitForStackValue(value); - __ Push(Smi::FromInt(NONE)); - __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); + __ CallRuntime(Runtime::kDefineClassMethod, 3); break; case ObjectLiteral::Property::GETTER: - VisitForStackValue(value); - __ Push(isolate()->factory()->null_value()); - __ Push(Smi::FromInt(NONE)); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassGetter, 3); break; case ObjectLiteral::Property::SETTER: - __ Push(isolate()->factory()->null_value()); - VisitForStackValue(value); - __ Push(Smi::FromInt(NONE)); - __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); + __ CallRuntime(Runtime::kDefineClassSetter, 3); break; default: diff --git a/test/mjsunit/harmony/classes.js b/test/mjsunit/harmony/classes.js index 9302b29..c5c2b72 100644 --- a/test/mjsunit/harmony/classes.js +++ b/test/mjsunit/harmony/classes.js @@ -439,6 +439,156 @@ function assertAccessorDescriptor(object, name) { })(); +(function TestSuperInMethods() { + class B { + method() { + return 1; + } + get x() { + return 2; + } + } + class C extends B { + method() { + assertEquals(2, super.x); + return super.method(); + } + } + assertEquals(1, new C().method()); +})(); + + +(function TestSuperInGetter() { + class B { + method() { + return 1; + } + get x() { + return 2; + } + } + class C extends B { + get y() { + assertEquals(2, super.x); + return super.method(); + } + } + assertEquals(1, new C().y); +})(); + + +(function TestSuperInSetter() { + class B { + method() { + return 1; + } + get x() { + return 2; + } + } + class C extends B { + set y(v) { + assertEquals(3, v); + assertEquals(2, super.x); + assertEquals(1, super.method()); + } + } + assertEquals(3, new C().y = 3); +})(); + + +(function TestSuperInStaticMethods() { + class B { + static method() { + return 1; + } + static get x() { + return 2; + } + } + class C extends B { + static method() { + assertEquals(2, super.x); + return super.method(); + } + } + assertEquals(1, C.method()); +})(); + + +(function TestSuperInStaticGetter() { + class B { + static method() { + return 1; + } + static get x() { + return 2; + } + } + class C extends B { + static get x() { + assertEquals(2, super.x); + return super.method(); + } + } + assertEquals(1, C.x); +})(); + + +(function TestSuperInStaticSetter() { + class B { + static method() { + return 1; + } + static get x() { + return 2; + } + } + class C extends B { + static set x(v) { + assertEquals(3, v); + assertEquals(2, super.x); + assertEquals(1, super.method()); + } + } + assertEquals(3, C.x = 3); +})(); + + +(function TestNumericPropertyNames() { + class B { + 1() { return 1; } + get 2() { return 2; } + set 3(_) {} + + static 4() { return 4; } + static get 5() { return 5; } + static set 6(_) {} + } + + assertMethodDescriptor(B.prototype, '1'); + assertGetterDescriptor(B.prototype, '2'); + assertSetterDescriptor(B.prototype, '3'); + + assertMethodDescriptor(B, '4'); + assertGetterDescriptor(B, '5'); + assertSetterDescriptor(B, '6'); + + class C extends B { + 1() { return super[1](); } + get 2() { return super[2]; } + + static 4() { return super[4](); } + static get 5() { return super[5]; } + } + + assertEquals(1, new C()[1]()); + assertEquals(2, new C()[2]); + assertEquals(4, C[4]()); + assertEquals(5, C[5]); +})(); + + /* TODO(arv): Implement (function TestNameBindingInConstructor() { class C {