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

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

Issue 1369293003: Wrap JSFunction bindings in a helper object (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Better wrapping. Created 5 years, 2 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } 350 }
351 return param_data; 351 return param_data;
352 } 352 }
353 } 353 }
354 354
355 355
356 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { 356 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
357 HandleScope scope(isolate); 357 HandleScope scope(isolate);
358 DCHECK(args.length() == 4); 358 DCHECK(args.length() == 4);
359 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); 359 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
360 CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1); 360 CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1);
Igor Sheludko 2015/10/01 08:03:35 While you are here: it looks like bindee must be a
mvstanton 2015/10/01 11:23:01 Good idea, done.
361 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); 361 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
362 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); 362 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
363 363
364 // TODO(lrn): Create bound function in C++ code from premade shared info. 364 // TODO(lrn): Create bound function in C++ code from premade shared info.
365 bound_function->shared()->set_bound(true); 365 bound_function->shared()->set_bound(true);
366 bound_function->shared()->set_optimized_code_map(Smi::FromInt(0)); 366 bound_function->shared()->set_optimized_code_map(Smi::FromInt(0));
367 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); 367 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
368 // Get all arguments of calling function (Function.prototype.bind). 368 // Get all arguments of calling function (Function.prototype.bind).
369 int argc = 0; 369 int argc = 0;
370 base::SmartArrayPointer<Handle<Object>> arguments = 370 base::SmartArrayPointer<Handle<Object>> arguments =
371 Runtime::GetCallerArguments(isolate, 0, &argc); 371 Runtime::GetCallerArguments(isolate, 0, &argc);
372 // Don't count the this-arg. 372 // Don't count the this-arg.
373 if (argc > 0) { 373 if (argc > 0) {
374 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); 374 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
375 argc--; 375 argc--;
376 } else { 376 } else {
377 RUNTIME_ASSERT(this_object->IsUndefined()); 377 RUNTIME_ASSERT(this_object->IsUndefined());
378 } 378 }
379 // Initialize array of bindings (function, this, and any existing arguments 379 // Initialize array of bindings (function, this, and any existing arguments
380 // if the function was already bound). 380 // if the function was already bound).
381 Handle<FixedArray> new_bindings; 381 Handle<BindingsArray> new_bindings;
382 int i; 382 int i;
Igor Sheludko 2015/10/01 08:03:35 Suggestion for better readability: int out_index =
mvstanton 2015/10/01 11:23:01 Done.
383 Handle<TypeFeedbackVector> vector(
384 bound_function->shared()->feedback_vector());
383 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { 385 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
384 Handle<FixedArray> old_bindings( 386 Handle<BindingsArray> old_bindings(
385 JSFunction::cast(*bindee)->function_bindings()); 387 JSFunction::cast(*bindee)->function_bindings());
386 RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex); 388 RUNTIME_ASSERT(old_bindings->bindings_count() >= 0);
387 new_bindings = 389 bindee = Handle<JSReceiver>(old_bindings->bound_function(), isolate);
Igor Sheludko 2015/10/01 08:03:35 nit: bindee = handle(old_bindings->bound_function(
mvstanton 2015/10/01 11:23:01 Done.
388 isolate->factory()->NewFixedArray(old_bindings->length() + argc); 390 Handle<Object> old_bound_this = handle(old_bindings->bound_this(), isolate);
Igor Sheludko 2015/10/01 08:03:35 nit: Handle<Object> old_bound_this(old_bindings->b
mvstanton 2015/10/01 11:23:01 Done.
389 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex), 391 new_bindings = BindingsArray::New(
390 isolate); 392 isolate, vector, Handle<JSReceiver>::cast(bindee), old_bound_this,
393 old_bindings->bindings_count() + argc);
391 i = 0; 394 i = 0;
Igor Sheludko 2015/10/01 08:03:35 Can be removed.
mvstanton 2015/10/01 11:23:01 Done.
392 for (int n = old_bindings->length(); i < n; i++) { 395 for (int n = old_bindings->bindings_count(); i < n; i++) {
393 new_bindings->set(i, old_bindings->get(i)); 396 new_bindings->set_binding(i, old_bindings->binding(i));
Igor Sheludko 2015/10/01 08:03:35 suggestion: new_bindings->set_binding(out_index, o
mvstanton 2015/10/01 11:23:01 Done.
394 } 397 }
395 } else { 398 } else {
396 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; 399 new_bindings = BindingsArray::New(
397 new_bindings = isolate->factory()->NewFixedArray(array_size); 400 isolate, vector, Handle<JSReceiver>::cast(bindee), this_object, argc);
398 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); 401 i = 0;
Igor Sheludko 2015/10/01 08:03:35 Can be removed.
mvstanton 2015/10/01 11:23:01 Done.
399 new_bindings->set(JSFunction::kBoundThisIndex, *this_object);
400 i = 2;
401 } 402 }
402 // Copy arguments, skipping the first which is "this_arg". 403 // Copy arguments, skipping the first which is "this_arg".
403 for (int j = 0; j < argc; j++, i++) { 404 for (int j = 0; j < argc; j++, i++) {
404 new_bindings->set(i, *arguments[j + 1]); 405 new_bindings->set_binding(i, *arguments[j + 1]);
405 } 406 }
406 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map()); 407 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
407 bound_function->set_function_bindings(*new_bindings); 408 bound_function->set_function_bindings(*new_bindings);
408 409
409 // Update length. Have to remove the prototype first so that map migration 410 // Update length. Have to remove the prototype first so that map migration
410 // is happy about the number of fields. 411 // is happy about the number of fields.
411 RUNTIME_ASSERT(bound_function->RemovePrototype()); 412 RUNTIME_ASSERT(bound_function->RemovePrototype());
412 413
413 // The new function should have the same [[Prototype]] as the bindee. 414 // The new function should have the same [[Prototype]] as the bindee.
414 Handle<Map> bound_function_map( 415 Handle<Map> bound_function_map(
(...skipping 23 matching lines...) Expand all
438 } 439 }
439 440
440 441
441 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { 442 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
442 HandleScope handles(isolate); 443 HandleScope handles(isolate);
443 DCHECK(args.length() == 1); 444 DCHECK(args.length() == 1);
444 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); 445 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
445 if (callable->IsJSFunction()) { 446 if (callable->IsJSFunction()) {
446 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); 447 Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
447 if (function->shared()->bound()) { 448 if (function->shared()->bound()) {
448 RUNTIME_ASSERT(function->function_bindings()->IsFixedArray()); 449 RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray());
449 Handle<FixedArray> bindings(function->function_bindings()); 450 Handle<BindingsArray> bindings(function->function_bindings());
450 return *isolate->factory()->NewJSArrayWithElements(bindings); 451 return *BindingsArray::CreateRuntimeBindings(bindings);
451 } 452 }
452 } 453 }
453 return isolate->heap()->undefined_value(); 454 return isolate->heap()->undefined_value();
454 } 455 }
455 456
456 457
457 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { 458 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
458 HandleScope scope(isolate); 459 HandleScope scope(isolate);
459 DCHECK(args.length() == 1); 460 DCHECK(args.length() == 1);
460 // First argument is a function to use as a constructor. 461 // First argument is a function to use as a constructor.
461 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 462 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
462 RUNTIME_ASSERT(function->shared()->bound()); 463 RUNTIME_ASSERT(function->shared()->bound());
463 464
464 // The argument is a bound function. Extract its bound arguments 465 // The argument is a bound function. Extract its bound arguments
465 // and callable. 466 // and callable.
466 Handle<FixedArray> bound_args = 467 Handle<BindingsArray> bound_args =
467 Handle<FixedArray>(FixedArray::cast(function->function_bindings())); 468 handle(BindingsArray::cast(function->function_bindings()));
468 int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex; 469 int bound_argc = bound_args->bindings_count();
469 Handle<Object> bound_function( 470 Handle<Object> bound_function(bound_args->bound_function(), isolate);
470 JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
471 isolate);
472 DCHECK(!bound_function->IsJSFunction() || 471 DCHECK(!bound_function->IsJSFunction() ||
473 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); 472 !Handle<JSFunction>::cast(bound_function)->shared()->bound());
474 473
475 int total_argc = 0; 474 int total_argc = 0;
476 base::SmartArrayPointer<Handle<Object>> param_data = 475 base::SmartArrayPointer<Handle<Object>> param_data =
477 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc); 476 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
478 for (int i = 0; i < bound_argc; i++) { 477 for (int i = 0; i < bound_argc; i++) {
479 param_data[i] = Handle<Object>( 478 param_data[i] = Handle<Object>(bound_args->binding(i), isolate);
Igor Sheludko 2015/10/01 08:03:35 nit: param_data[i] = handle(bound_args->binding(i)
mvstanton 2015/10/01 11:23:01 Done.
480 bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate);
481 } 479 }
482 480
483 Handle<Object> result; 481 Handle<Object> result;
484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
485 isolate, result, Execution::New(isolate, bound_function, bound_function, 483 isolate, result, Execution::New(isolate, bound_function, bound_function,
486 total_argc, param_data.get())); 484 total_argc, param_data.get()));
487 return *result; 485 return *result;
488 } 486 }
489 487
490 488
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 602
605 603
606 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { 604 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) {
607 HandleScope scope(isolate); 605 HandleScope scope(isolate);
608 DCHECK(args.length() == 0); 606 DCHECK(args.length() == 0);
609 THROW_NEW_ERROR_RETURN_FAILURE(isolate, 607 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
610 NewTypeError(MessageTemplate::kStrongArity)); 608 NewTypeError(MessageTemplate::kStrongArity));
611 } 609 }
612 } // namespace internal 610 } // namespace internal
613 } // namespace v8 611 } // 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