Index: src/runtime/runtime-function.cc |
diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc |
index 75aeed74bed77f96de8da9cb4014bdabd73e84d5..230147ed06c3c5f7e510e869af4a0651d04c02a7 100644 |
--- a/src/runtime/runtime-function.cc |
+++ b/src/runtime/runtime-function.cc |
@@ -574,14 +574,11 @@ RUNTIME_FUNCTION(Runtime_Call) { |
} |
-RUNTIME_FUNCTION(Runtime_Apply) { |
+static Object* ApplyHelper(Isolate* isolate, Handle<JSReceiver> fun, |
+ Handle<Object> receiver, Handle<JSObject> arguments, |
+ int32_t offset, int32_t argc, bool is_construct) { |
HandleScope scope(isolate); |
- DCHECK(args.length() == 5); |
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0); |
- CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
- CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2); |
- CONVERT_INT32_ARG_CHECKED(offset, 3); |
- CONVERT_INT32_ARG_CHECKED(argc, 4); |
+ |
RUNTIME_ASSERT(offset >= 0); |
// Loose upper bound to allow fuzzing. We'll most likely run out of |
// stack space before hitting this limit. |
@@ -605,13 +602,100 @@ RUNTIME_FUNCTION(Runtime_Apply) { |
} |
Handle<Object> result; |
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
- isolate, result, |
- Execution::Call(isolate, fun, receiver, argc, argv, true)); |
+ if (is_construct) { |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, result, Execution::New( |
+ Handle<JSFunction>::cast(fun), argc, argv)); |
+ } else { |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, result, |
+ Execution::Call(isolate, fun, receiver, argc, argv, true)); |
+ } |
return *result; |
} |
+RUNTIME_FUNCTION(Runtime_Apply) { |
+ HandleScope scope(isolate); |
+ DCHECK(args.length() == 5); |
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2); |
+ CONVERT_INT32_ARG_CHECKED(offset, 3); |
+ CONVERT_INT32_ARG_CHECKED(argc, 4); |
+ |
+ return ApplyHelper(isolate, fun, receiver, arguments, offset, argc, false); |
+} |
+ |
+ |
+static bool GetObjectLength(Isolate* isolate, Handle<JSObject> obj, |
+ int32_t* length) { |
+ HandleScope scope(isolate); |
+ if (obj->IsJSArray()) { |
+ return Handle<JSArray>::cast(obj)->length()->ToInt32(length); |
+ } else { |
+ Handle<Object> val; |
+ Handle<Object> key(isolate->heap()->length_string(), isolate); |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, |
+ Runtime::GetObjectProperty(isolate, obj, key), false); |
+ // TODO(caitp): Support larger element indexes (up to 2^53-1). |
rossberg
2015/02/25 14:28:19
Ah, no. We likely won't, ever, at least not for ca
caitp (gmail)
2015/02/25 14:49:08
sorry, that's copy/pasted from similar code I wrot
|
+ if (!val->ToInt32(length)) { |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, |
rossberg
2015/02/25 14:28:19
I think it's more adequate to raise an exception h
caitp (gmail)
2015/02/25 14:49:08
The only reason ToLength() would throw is if the v
|
+ Execution::ToLength(isolate, val), false); |
+ return val->ToInt32(length); |
+ } |
+ } |
+ return true; |
+} |
+ |
+ |
+RUNTIME_FUNCTION(Runtime_ApplyCall) { |
+ HandleScope scope(isolate); |
+ DCHECK(args.length() == 3); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, fun, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2); |
+ |
+ if (!fun->IsJSFunction()) { |
rossberg
2015/02/25 14:28:19
Why is this needed? Isn't that already taken care
|
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, fun, Execution::TryGetFunctionDelegate(isolate, fun)); |
+ } |
+ |
+ int32_t length = 0; |
+ if (!GetObjectLength(isolate, arguments, &length)) { |
+ if (isolate->has_pending_exception()) { |
+ return isolate->heap()->exception(); |
+ } |
+ } |
+ |
+ return ApplyHelper(isolate, Handle<JSReceiver>::cast(fun), receiver, |
+ arguments, 0, length, false); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(Runtime_ApplyConstruct) { |
+ HandleScope scope(isolate); |
+ DCHECK(args.length() == 2); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, fun, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 1); |
+ |
+ if (!fun->IsJSFunction()) { |
rossberg
2015/02/25 14:28:19
In a similar vein, this logic belongs into Executi
caitp (gmail)
2015/02/25 14:49:08
The problem with letting Execution::New() and Exec
|
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, fun, Execution::TryGetConstructorDelegate(isolate, fun)); |
+ } |
+ |
+ int32_t length = 0; |
+ if (!GetObjectLength(isolate, arguments, &length)) { |
+ if (isolate->has_pending_exception()) { |
+ return isolate->heap()->exception(); |
+ } |
+ } |
+ |
+ return ApplyHelper(isolate, Handle<JSReceiver>::cast(fun), fun, arguments, 0, |
+ length, true); |
+} |
+ |
+ |
RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) { |
HandleScope scope(isolate); |
DCHECK(args.length() == 1); |