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

Unified Diff: src/runtime/runtime-function.cc

Issue 1552473002: Revert of [runtime] Introduce dedicated JSBoundFunction to represent bound functions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@FunctionConstructor
Patch Set: Created 5 years 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
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/runtime/runtime-object.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime/runtime-function.cc
diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc
index 24ed128f670a039c635e4b39a7277d5e50a33ca5..9ec4cda81a11f4f2cfab49c28d7a8804599d75ea 100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -53,23 +53,23 @@
RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
-
- if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
- Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(),
- isolate);
+ DCHECK(args.length() == 1);
+
+ CONVERT_ARG_CHECKED(JSFunction, fun, 0);
+ Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
if (!script->IsScript()) return isolate->heap()->undefined_value();
+
return *Script::GetWrapper(Handle<Script>::cast(script));
}
RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
HandleScope scope(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
- if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
- return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode();
+ DCHECK(args.length() == 1);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
+ Handle<SharedFunctionInfo> shared(f->shared());
+ return *shared->GetSourceCode();
}
@@ -152,6 +152,7 @@
Handle<SharedFunctionInfo> target_shared(target->shared());
Handle<SharedFunctionInfo> source_shared(source->shared());
+ RUNTIME_ASSERT(!source_shared->bound());
if (!Compiler::Compile(source, KEEP_EXCEPTION)) {
return isolate->heap()->exception();
@@ -308,6 +309,137 @@
}
+RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 5);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, bindee, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
+ CONVERT_ARG_HANDLE_CHECKED(Object, proto, 4);
+
+ // TODO(lrn): Create bound function in C++ code from premade shared info.
+ bound_function->shared()->set_bound(true);
+ bound_function->shared()->set_optimized_code_map(
+ isolate->heap()->cleared_optimized_code_map());
+ bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
+ bound_function->shared()->set_construct_stub(
+ *isolate->builtins()->JSBuiltinsConstructStub());
+ // Get all arguments of calling function (Function.prototype.bind).
+ int argc = 0;
+ base::SmartArrayPointer<Handle<Object>> arguments =
+ Runtime::GetCallerArguments(isolate, 0, &argc);
+ // Don't count the this-arg.
+ if (argc > 0) {
+ RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
+ argc--;
+ } else {
+ RUNTIME_ASSERT(this_object->IsUndefined());
+ }
+ // Initialize array of bindings (function, this, and any existing arguments
+ // if the function was already bound).
+ Handle<BindingsArray> new_bindings;
+ int out_index = 0;
+ Handle<TypeFeedbackVector> vector(
+ bound_function->shared()->feedback_vector());
+ if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
+ Handle<BindingsArray> old_bindings(
+ JSFunction::cast(*bindee)->function_bindings());
+ RUNTIME_ASSERT(old_bindings->bindings_count() >= 0);
+ bindee = handle(old_bindings->bound_function(), isolate);
+ Handle<Object> old_bound_this(old_bindings->bound_this(), isolate);
+ new_bindings = BindingsArray::New(isolate, vector, bindee, old_bound_this,
+ old_bindings->bindings_count() + argc);
+ for (int n = old_bindings->bindings_count(); out_index < n; out_index++) {
+ new_bindings->set_binding(out_index, old_bindings->binding(out_index));
+ }
+ } else {
+ new_bindings =
+ BindingsArray::New(isolate, vector, bindee, this_object, argc);
+ }
+ // Copy arguments, skipping the first which is "this_arg".
+ for (int j = 0; j < argc; j++, out_index++) {
+ new_bindings->set_binding(out_index, *arguments[j + 1]);
+ }
+ new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
+ bound_function->set_function_bindings(*new_bindings);
+
+ // Update length. Have to remove the prototype first so that map migration
+ // is happy about the number of fields.
+ RUNTIME_ASSERT(bound_function->RemovePrototype());
+
+ // The new function should have the given prototype.
+ Handle<Map> bound_function_map =
+ bindee->IsConstructor()
+ ? isolate->bound_function_with_constructor_map()
+ : isolate->bound_function_without_constructor_map();
+ if (bound_function_map->prototype() != *proto) {
+ bound_function_map = Map::TransitionToPrototype(bound_function_map, proto,
+ REGULAR_PROTOTYPE);
+ }
+ JSObject::MigrateToMap(bound_function, bound_function_map);
+ DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor());
+
+ Handle<String> length_string = isolate->factory()->length_string();
+ // These attributes must be kept in sync with how the bootstrapper
+ // configures the bound_function_map retrieved above.
+ // We use ...IgnoreAttributes() here because of length's read-onliness.
+ PropertyAttributes attr =
+ static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate, JSObject::SetOwnPropertyIgnoreAttributes(
+ bound_function, length_string, new_length, attr));
+ return *bound_function;
+}
+
+
+RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
+ HandleScope handles(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
+ if (callable->IsJSFunction()) {
+ Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
+ if (function->shared()->bound()) {
+ RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray());
+ Handle<BindingsArray> bindings(function->function_bindings());
+ return *BindingsArray::CreateRuntimeBindings(bindings);
+ }
+ }
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ // First argument is a function to use as a constructor.
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ RUNTIME_ASSERT(function->shared()->bound());
+
+ // The argument is a bound function. Extract its bound arguments
+ // and callable.
+ Handle<BindingsArray> bound_args =
+ handle(BindingsArray::cast(function->function_bindings()));
+ int bound_argc = bound_args->bindings_count();
+ Handle<Object> bound_function(bound_args->bound_function(), isolate);
+ DCHECK(!bound_function->IsJSFunction() ||
+ !Handle<JSFunction>::cast(bound_function)->shared()->bound());
+
+ int total_argc = 0;
+ base::SmartArrayPointer<Handle<Object>> param_data =
+ Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
+ for (int i = 0; i < bound_argc; i++) {
+ param_data[i] = handle(bound_args->binding(i), isolate);
+ }
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, Execution::New(isolate, bound_function, bound_function,
+ total_argc, param_data.get()));
+ return *result;
+}
+
+
RUNTIME_FUNCTION(Runtime_Call) {
HandleScope scope(isolate);
DCHECK_LE(2, args.length());
@@ -395,9 +527,9 @@
RUNTIME_FUNCTION(Runtime_IsFunction) {
SealHandleScope shs(isolate);
- DCHECK_EQ(1, args.length());
- CONVERT_ARG_CHECKED(Object, object, 0);
- return isolate->heap()->ToBoolean(object->IsFunction());
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
+ return isolate->heap()->ToBoolean(obj->IsJSFunction());
}
@@ -412,11 +544,8 @@
RUNTIME_FUNCTION(Runtime_FunctionToString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
- return function->IsJSBoundFunction()
- ? *JSBoundFunction::ToString(
- Handle<JSBoundFunction>::cast(function))
- : *JSFunction::ToString(Handle<JSFunction>::cast(function));
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ return *JSFunction::ToString(function);
}
} // namespace internal
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/runtime/runtime-object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698