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

Side by Side Diff: src/runtime/runtime-function.cc

Issue 1542963002: [runtime] Introduce dedicated JSBoundFunction to represent bound functions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@FunctionConstructor
Patch Set: [arm64] Poke does not preserve flags with --debug-code. Created 4 years, 11 months 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 unified diff | Download patch
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/runtime/runtime-object.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/deoptimizer.h" 10 #include "src/deoptimizer.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 RUNTIME_ASSERT(f->RemovePrototype()); 46 RUNTIME_ASSERT(f->RemovePrototype());
47 f->shared()->set_construct_stub( 47 f->shared()->set_construct_stub(
48 *isolate->builtins()->ConstructedNonConstructable()); 48 *isolate->builtins()->ConstructedNonConstructable());
49 49
50 return isolate->heap()->undefined_value(); 50 return isolate->heap()->undefined_value();
51 } 51 }
52 52
53 53
54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { 54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
55 HandleScope scope(isolate); 55 HandleScope scope(isolate);
56 DCHECK(args.length() == 1); 56 DCHECK_EQ(1, args.length());
57 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
57 58
58 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 59 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
59 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate); 60 Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(),
61 isolate);
60 if (!script->IsScript()) return isolate->heap()->undefined_value(); 62 if (!script->IsScript()) return isolate->heap()->undefined_value();
61
62 return *Script::GetWrapper(Handle<Script>::cast(script)); 63 return *Script::GetWrapper(Handle<Script>::cast(script));
63 } 64 }
64 65
65 66
66 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { 67 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
67 HandleScope scope(isolate); 68 HandleScope scope(isolate);
68 DCHECK(args.length() == 1); 69 DCHECK_EQ(1, args.length());
69 70 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
70 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); 71 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
71 Handle<SharedFunctionInfo> shared(f->shared()); 72 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode();
72 return *shared->GetSourceCode();
73 } 73 }
74 74
75 75
76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { 76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
77 SealHandleScope shs(isolate); 77 SealHandleScope shs(isolate);
78 DCHECK(args.length() == 1); 78 DCHECK(args.length() == 1);
79 79
80 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 80 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
81 int pos = fun->shared()->start_position(); 81 int pos = fun->shared()->start_position();
82 return Smi::FromInt(pos); 82 return Smi::FromInt(pos);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 145
146 RUNTIME_FUNCTION(Runtime_SetCode) { 146 RUNTIME_FUNCTION(Runtime_SetCode) {
147 HandleScope scope(isolate); 147 HandleScope scope(isolate);
148 DCHECK(args.length() == 2); 148 DCHECK(args.length() == 2);
149 149
150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); 150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); 151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
152 152
153 Handle<SharedFunctionInfo> target_shared(target->shared()); 153 Handle<SharedFunctionInfo> target_shared(target->shared());
154 Handle<SharedFunctionInfo> source_shared(source->shared()); 154 Handle<SharedFunctionInfo> source_shared(source->shared());
155 RUNTIME_ASSERT(!source_shared->bound());
156 155
157 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { 156 if (!Compiler::Compile(source, KEEP_EXCEPTION)) {
158 return isolate->heap()->exception(); 157 return isolate->heap()->exception();
159 } 158 }
160 159
161 // Mark both, the source and the target, as un-flushable because the 160 // Mark both, the source and the target, as un-flushable because the
162 // shared unoptimized code makes them impossible to enqueue in a list. 161 // shared unoptimized code makes them impossible to enqueue in a list.
163 DCHECK(target_shared->code()->gc_metadata() == NULL); 162 DCHECK(target_shared->code()->gc_metadata() == NULL);
164 DCHECK(source_shared->code()->gc_metadata() == NULL); 163 DCHECK(source_shared->code()->gc_metadata() == NULL);
165 target_shared->set_dont_flush(true); 164 target_shared->set_dont_flush(true);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 NewArray<Handle<Object> >(*total_argc)); 301 NewArray<Handle<Object> >(*total_argc));
303 for (int i = 0; i < args_count; i++) { 302 for (int i = 0; i < args_count; i++) {
304 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); 303 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
305 param_data[prefix_argc + i] = val; 304 param_data[prefix_argc + i] = val;
306 } 305 }
307 return param_data; 306 return param_data;
308 } 307 }
309 } 308 }
310 309
311 310
312 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
313 HandleScope scope(isolate);
314 DCHECK(args.length() == 5);
315 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
316 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, bindee, 1);
317 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
318 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
319 CONVERT_ARG_HANDLE_CHECKED(Object, proto, 4);
320
321 // TODO(lrn): Create bound function in C++ code from premade shared info.
322 bound_function->shared()->set_bound(true);
323 bound_function->shared()->set_optimized_code_map(
324 isolate->heap()->cleared_optimized_code_map());
325 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
326 bound_function->shared()->set_construct_stub(
327 *isolate->builtins()->JSBuiltinsConstructStub());
328 // Get all arguments of calling function (Function.prototype.bind).
329 int argc = 0;
330 base::SmartArrayPointer<Handle<Object>> arguments =
331 Runtime::GetCallerArguments(isolate, 0, &argc);
332 // Don't count the this-arg.
333 if (argc > 0) {
334 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
335 argc--;
336 } else {
337 RUNTIME_ASSERT(this_object->IsUndefined());
338 }
339 // Initialize array of bindings (function, this, and any existing arguments
340 // if the function was already bound).
341 Handle<BindingsArray> new_bindings;
342 int out_index = 0;
343 Handle<TypeFeedbackVector> vector(
344 bound_function->shared()->feedback_vector());
345 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
346 Handle<BindingsArray> old_bindings(
347 JSFunction::cast(*bindee)->function_bindings());
348 RUNTIME_ASSERT(old_bindings->bindings_count() >= 0);
349 bindee = handle(old_bindings->bound_function(), isolate);
350 Handle<Object> old_bound_this(old_bindings->bound_this(), isolate);
351 new_bindings = BindingsArray::New(isolate, vector, bindee, old_bound_this,
352 old_bindings->bindings_count() + argc);
353 for (int n = old_bindings->bindings_count(); out_index < n; out_index++) {
354 new_bindings->set_binding(out_index, old_bindings->binding(out_index));
355 }
356 } else {
357 new_bindings =
358 BindingsArray::New(isolate, vector, bindee, this_object, argc);
359 }
360 // Copy arguments, skipping the first which is "this_arg".
361 for (int j = 0; j < argc; j++, out_index++) {
362 new_bindings->set_binding(out_index, *arguments[j + 1]);
363 }
364 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
365 bound_function->set_function_bindings(*new_bindings);
366
367 // Update length. Have to remove the prototype first so that map migration
368 // is happy about the number of fields.
369 RUNTIME_ASSERT(bound_function->RemovePrototype());
370
371 // The new function should have the given prototype.
372 Handle<Map> bound_function_map =
373 bindee->IsConstructor()
374 ? isolate->bound_function_with_constructor_map()
375 : isolate->bound_function_without_constructor_map();
376 if (bound_function_map->prototype() != *proto) {
377 bound_function_map = Map::TransitionToPrototype(bound_function_map, proto,
378 REGULAR_PROTOTYPE);
379 }
380 JSObject::MigrateToMap(bound_function, bound_function_map);
381 DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor());
382
383 Handle<String> length_string = isolate->factory()->length_string();
384 // These attributes must be kept in sync with how the bootstrapper
385 // configures the bound_function_map retrieved above.
386 // We use ...IgnoreAttributes() here because of length's read-onliness.
387 PropertyAttributes attr =
388 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
389 RETURN_FAILURE_ON_EXCEPTION(
390 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
391 bound_function, length_string, new_length, attr));
392 return *bound_function;
393 }
394
395
396 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
397 HandleScope handles(isolate);
398 DCHECK(args.length() == 1);
399 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
400 if (callable->IsJSFunction()) {
401 Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
402 if (function->shared()->bound()) {
403 RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray());
404 Handle<BindingsArray> bindings(function->function_bindings());
405 return *BindingsArray::CreateRuntimeBindings(bindings);
406 }
407 }
408 return isolate->heap()->undefined_value();
409 }
410
411
412 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
413 HandleScope scope(isolate);
414 DCHECK(args.length() == 1);
415 // First argument is a function to use as a constructor.
416 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
417 RUNTIME_ASSERT(function->shared()->bound());
418
419 // The argument is a bound function. Extract its bound arguments
420 // and callable.
421 Handle<BindingsArray> bound_args =
422 handle(BindingsArray::cast(function->function_bindings()));
423 int bound_argc = bound_args->bindings_count();
424 Handle<Object> bound_function(bound_args->bound_function(), isolate);
425 DCHECK(!bound_function->IsJSFunction() ||
426 !Handle<JSFunction>::cast(bound_function)->shared()->bound());
427
428 int total_argc = 0;
429 base::SmartArrayPointer<Handle<Object>> param_data =
430 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
431 for (int i = 0; i < bound_argc; i++) {
432 param_data[i] = handle(bound_args->binding(i), isolate);
433 }
434
435 Handle<Object> result;
436 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
437 isolate, result, Execution::New(isolate, bound_function, bound_function,
438 total_argc, param_data.get()));
439 return *result;
440 }
441
442
443 RUNTIME_FUNCTION(Runtime_Call) { 311 RUNTIME_FUNCTION(Runtime_Call) {
444 HandleScope scope(isolate); 312 HandleScope scope(isolate);
445 DCHECK_LE(2, args.length()); 313 DCHECK_LE(2, args.length());
446 int const argc = args.length() - 2; 314 int const argc = args.length() - 2;
447 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); 315 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
448 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); 316 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
449 ScopedVector<Handle<Object>> argv(argc); 317 ScopedVector<Handle<Object>> argv(argc);
450 for (int i = 0; i < argc; ++i) { 318 for (int i = 0; i < argc; ++i) {
451 argv[i] = args.at<Object>(2 + i); 319 argv[i] = args.at<Object>(2 + i);
452 } 320 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); 388 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
521 if (receiver->IsNull() || receiver->IsUndefined()) { 389 if (receiver->IsNull() || receiver->IsUndefined()) {
522 return isolate->global_proxy(); 390 return isolate->global_proxy();
523 } 391 }
524 return *Object::ToObject(isolate, receiver).ToHandleChecked(); 392 return *Object::ToObject(isolate, receiver).ToHandleChecked();
525 } 393 }
526 394
527 395
528 RUNTIME_FUNCTION(Runtime_IsFunction) { 396 RUNTIME_FUNCTION(Runtime_IsFunction) {
529 SealHandleScope shs(isolate); 397 SealHandleScope shs(isolate);
530 DCHECK(args.length() == 1); 398 DCHECK_EQ(1, args.length());
531 CONVERT_ARG_CHECKED(Object, obj, 0); 399 CONVERT_ARG_CHECKED(Object, object, 0);
532 return isolate->heap()->ToBoolean(obj->IsJSFunction()); 400 return isolate->heap()->ToBoolean(object->IsFunction());
533 } 401 }
534 402
535 403
536 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { 404 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) {
537 HandleScope scope(isolate); 405 HandleScope scope(isolate);
538 DCHECK(args.length() == 0); 406 DCHECK(args.length() == 0);
539 THROW_NEW_ERROR_RETURN_FAILURE(isolate, 407 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
540 NewTypeError(MessageTemplate::kStrongArity)); 408 NewTypeError(MessageTemplate::kStrongArity));
541 } 409 }
542 410
543 411
544 RUNTIME_FUNCTION(Runtime_FunctionToString) { 412 RUNTIME_FUNCTION(Runtime_FunctionToString) {
545 HandleScope scope(isolate); 413 HandleScope scope(isolate);
546 DCHECK_EQ(1, args.length()); 414 DCHECK_EQ(1, args.length());
547 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 415 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
548 return *JSFunction::ToString(function); 416 return function->IsJSBoundFunction()
417 ? *JSBoundFunction::ToString(
418 Handle<JSBoundFunction>::cast(function))
419 : *JSFunction::ToString(Handle<JSFunction>::cast(function));
549 } 420 }
550 421
551 } // namespace internal 422 } // namespace internal
552 } // namespace v8 423 } // namespace v8
OLDNEW
« 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