Revision: 25268
Author: [email protected]
Date: Tue Nov 11 15:54:33 2014 UTC
Log: Classes: Add support for arguments in default constructor
This is currently done by generating a default constructor that looks
like this:
constructor() {
%DefaultConstructorSuperCall();
}
The a runtime function implements the logic which is pretty similar to
Runtime_Apply except that it uses the [[Prototype]] of the current
function.
BUG=v8:3672
LOG=Y
[email protected]
Review URL: https://codereview.chromium.org/692333011
https://code.google.com/p/v8/source/detail?r=25268
Modified:
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/runtime/runtime-classes.cc
/branches/bleeding_edge/src/runtime/runtime-object.cc
/branches/bleeding_edge/src/runtime/runtime.h
/branches/bleeding_edge/test/mjsunit/harmony/classes.js
=======================================
--- /branches/bleeding_edge/src/parser.cc Mon Nov 10 09:35:28 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc Tue Nov 11 15:54:33 2014 UTC
@@ -302,10 +302,12 @@
body = new (zone()) ZoneList<Statement*>(1, zone());
if (call_super) {
- Expression* prop = SuperReference(function_scope, factory(), pos);
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(0, zone());
- Call* call = factory()->NewCall(prop, args, pos);
+ CallRuntime* call = factory()->NewCallRuntime(
+ ast_value_factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kDefaultConstructorSuperCall),
args,
+ pos);
body->Add(factory()->NewExpressionStatement(call, pos), zone());
}
=======================================
--- /branches/bleeding_edge/src/runtime/runtime-classes.cc Fri Nov 7
16:39:00 2014 UTC
+++ /branches/bleeding_edge/src/runtime/runtime-classes.cc Tue Nov 11
15:54:33 2014 UTC
@@ -448,5 +448,52 @@
return StoreKeyedToSuper(isolate, home_object, receiver, key, value,
SLOPPY);
}
+
+
+RUNTIME_FUNCTION(Runtime_DefaultConstructorSuperCall) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+
+ // Compute the frame holding the arguments.
+ JavaScriptFrameIterator it(isolate);
+ it.AdvanceToArgumentsFrame();
+ JavaScriptFrame* frame = it.frame();
+
+ Handle<JSFunction> function(frame->function(), isolate);
+ Handle<Object> receiver(frame->receiver(), isolate);
+
+ Handle<Object> proto_function;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, proto_function,
+ Runtime::GetPrototype(isolate,
function));
+
+ // Get the actual number of provided arguments.
+ const int argc = frame->ComputeParametersCount();
+
+ // Loose upper bound to allow fuzzing. We'll most likely run out of
+ // stack space before hitting this limit.
+ static int kMaxArgc = 1000000;
+ RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
+
+ // If there are too many arguments, allocate argv via malloc.
+ const int argv_small_size = 10;
+ Handle<Object> argv_small_buffer[argv_small_size];
+ SmartArrayPointer<Handle<Object> > argv_large_buffer;
+ Handle<Object>* argv = argv_small_buffer;
+ if (argc > argv_small_size) {
+ argv = new Handle<Object>[argc];
+ if (argv == NULL) return isolate->StackOverflow();
+ argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
+ }
+
+ for (int i = 0; i < argc; ++i) {
+ argv[i] = handle(frame->GetParameter(i), isolate);
+ }
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, proto_function, receiver, argc, argv,
false));
+ return *result;
+}
}
} // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/runtime/runtime-object.cc Tue Nov 11
15:40:51 2014 UTC
+++ /branches/bleeding_edge/src/runtime/runtime-object.cc Tue Nov 11
15:54:33 2014 UTC
@@ -242,10 +242,8 @@
}
-RUNTIME_FUNCTION(Runtime_GetPrototype) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
+MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
+ Handle<Object> obj) {
// We don't expect access checks to be needed on JSProxy objects.
DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
PrototypeIterator iter(isolate, obj,
PrototypeIterator::START_AT_RECEIVER);
@@ -257,15 +255,26 @@
isolate->ReportFailedAccessCheck(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
v8::ACCESS_GET);
- RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
- return isolate->heap()->undefined_value();
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ return isolate->factory()->undefined_value();
}
iter.AdvanceIgnoringProxies();
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
- return *PrototypeIterator::GetCurrent(iter);
+ return PrototypeIterator::GetCurrent(iter);
}
} while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
- return *PrototypeIterator::GetCurrent(iter);
+ return PrototypeIterator::GetCurrent(iter);
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetPrototype) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ Runtime::GetPrototype(isolate, obj));
+ return *result;
}
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.h Tue Nov 11 09:46:40 2014
UTC
+++ /branches/bleeding_edge/src/runtime/runtime.h Tue Nov 11 15:54:33 2014
UTC
@@ -199,7 +199,8 @@
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \
F(StoreKeyedToSuper_Strict, 4, 1) \
- F(StoreKeyedToSuper_Sloppy, 4, 1)
+ F(StoreKeyedToSuper_Sloppy, 4, 1) \
+ F(DefaultConstructorSuperCall, 0, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
@@ -828,6 +829,9 @@
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key);
+ MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
+ Isolate* isolate, Handle<Object> object);
+
MUST_USE_RESULT static MaybeHandle<Name> ToName(Isolate* isolate,
Handle<Object> key);
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/classes.js Fri Nov 7
16:39:00 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/harmony/classes.js Tue Nov 11
15:54:33 2014 UTC
@@ -624,6 +624,55 @@
})();
+(function TestDefaultConstructorArguments() {
+ var args, self;
+ class Base {
+ constructor() {
+ self = this;
+ args = arguments;
+ }
+ }
+ class Derived extends Base {}
+
+ new Derived;
+ assertEquals(0, args.length);
+
+ new Derived(0, 1, 2);
+ assertEquals(3, args.length);
+ assertTrue(self instanceof Derived);
+
+ var arr = new Array(1e5);
+ var obj = {};
+ Derived.apply(obj, arr);
+ assertEquals(1e5, args.length);
+ assertEquals(obj, self);
+})();
+
+
+(function TestDefaultConstructorArguments2() {
+ var args;
+ class Base {
+ constructor(x, y) {
+ args = arguments;
+ }
+ }
+ class Derived extends Base {}
+
+ new Derived;
+ assertEquals(0, args.length);
+
+ new Derived(1);
+ assertEquals(1, args.length);
+ assertEquals(1, args[0]);
+
+ new Derived(1, 2, 3);
+ assertEquals(3, args.length);
+ assertEquals(1, args[0]);
+ assertEquals(2, args[1]);
+ assertEquals(3, args[2]);
+})();
+
+
/* TODO(arv): Implement
(function TestNameBindingInConstructor() {
class C {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.