Chromium Code Reviews| 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); |