OLD | NEW |
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/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 397 } |
398 | 398 |
399 RETURN_FAILURE_ON_EXCEPTION( | 399 RETURN_FAILURE_ON_EXCEPTION( |
400 isolate, JSObject::SetOwnPropertyIgnoreAttributes( | 400 isolate, JSObject::SetOwnPropertyIgnoreAttributes( |
401 Handle<JSObject>::cast(holder), name, value, attr)); | 401 Handle<JSObject>::cast(holder), name, value, attr)); |
402 | 402 |
403 return *value; | 403 return *value; |
404 } | 404 } |
405 | 405 |
406 | 406 |
407 static Handle<JSObject> NewSloppyArguments(Isolate* isolate, | 407 namespace { |
408 Handle<JSFunction> callee, | 408 |
409 Object** parameters, | 409 template <typename T> |
410 int argument_count) { | 410 Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee, |
| 411 T parameters, int argument_count) { |
411 CHECK(!IsSubclassConstructor(callee->shared()->kind())); | 412 CHECK(!IsSubclassConstructor(callee->shared()->kind())); |
412 DCHECK(callee->has_simple_parameters()); | 413 DCHECK(callee->has_simple_parameters()); |
413 Handle<JSObject> result = | 414 Handle<JSObject> result = |
414 isolate->factory()->NewArgumentsObject(callee, argument_count); | 415 isolate->factory()->NewArgumentsObject(callee, argument_count); |
415 | 416 |
416 // Allocate the elements if needed. | 417 // Allocate the elements if needed. |
417 int parameter_count = callee->shared()->internal_formal_parameter_count(); | 418 int parameter_count = callee->shared()->internal_formal_parameter_count(); |
418 if (argument_count > 0) { | 419 if (argument_count > 0) { |
419 if (parameter_count > 0) { | 420 if (parameter_count > 0) { |
420 int mapped_count = Min(argument_count, parameter_count); | 421 int mapped_count = Min(argument_count, parameter_count); |
421 Handle<FixedArray> parameter_map = | 422 Handle<FixedArray> parameter_map = |
422 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); | 423 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); |
423 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map()); | 424 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map()); |
424 result->set_map(isolate->native_context()->fast_aliased_arguments_map()); | 425 result->set_map(isolate->native_context()->fast_aliased_arguments_map()); |
425 result->set_elements(*parameter_map); | 426 result->set_elements(*parameter_map); |
426 | 427 |
427 // Store the context and the arguments array at the beginning of the | 428 // Store the context and the arguments array at the beginning of the |
428 // parameter map. | 429 // parameter map. |
429 Handle<Context> context(isolate->context()); | 430 Handle<Context> context(isolate->context()); |
430 Handle<FixedArray> arguments = | 431 Handle<FixedArray> arguments = |
431 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); | 432 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
432 parameter_map->set(0, *context); | 433 parameter_map->set(0, *context); |
433 parameter_map->set(1, *arguments); | 434 parameter_map->set(1, *arguments); |
434 | 435 |
435 // Loop over the actual parameters backwards. | 436 // Loop over the actual parameters backwards. |
436 int index = argument_count - 1; | 437 int index = argument_count - 1; |
437 while (index >= mapped_count) { | 438 while (index >= mapped_count) { |
438 // These go directly in the arguments array and have no | 439 // These go directly in the arguments array and have no |
439 // corresponding slot in the parameter map. | 440 // corresponding slot in the parameter map. |
440 arguments->set(index, *(parameters - index - 1)); | 441 arguments->set(index, parameters[index]); |
441 --index; | 442 --index; |
442 } | 443 } |
443 | 444 |
444 Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); | 445 Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); |
445 while (index >= 0) { | 446 while (index >= 0) { |
446 // Detect duplicate names to the right in the parameter list. | 447 // Detect duplicate names to the right in the parameter list. |
447 Handle<String> name(scope_info->ParameterName(index)); | 448 Handle<String> name(scope_info->ParameterName(index)); |
448 int context_local_count = scope_info->ContextLocalCount(); | 449 int context_local_count = scope_info->ContextLocalCount(); |
449 bool duplicate = false; | 450 bool duplicate = false; |
450 for (int j = index + 1; j < parameter_count; ++j) { | 451 for (int j = index + 1; j < parameter_count; ++j) { |
451 if (scope_info->ParameterName(j) == *name) { | 452 if (scope_info->ParameterName(j) == *name) { |
452 duplicate = true; | 453 duplicate = true; |
453 break; | 454 break; |
454 } | 455 } |
455 } | 456 } |
456 | 457 |
457 if (duplicate) { | 458 if (duplicate) { |
458 // This goes directly in the arguments array with a hole in the | 459 // This goes directly in the arguments array with a hole in the |
459 // parameter map. | 460 // parameter map. |
460 arguments->set(index, *(parameters - index - 1)); | 461 arguments->set(index, parameters[index]); |
461 parameter_map->set_the_hole(index + 2); | 462 parameter_map->set_the_hole(index + 2); |
462 } else { | 463 } else { |
463 // The context index goes in the parameter map with a hole in the | 464 // The context index goes in the parameter map with a hole in the |
464 // arguments array. | 465 // arguments array. |
465 int context_index = -1; | 466 int context_index = -1; |
466 for (int j = 0; j < context_local_count; ++j) { | 467 for (int j = 0; j < context_local_count; ++j) { |
467 if (scope_info->ContextLocalName(j) == *name) { | 468 if (scope_info->ContextLocalName(j) == *name) { |
468 context_index = j; | 469 context_index = j; |
469 break; | 470 break; |
470 } | 471 } |
471 } | 472 } |
472 | 473 |
473 DCHECK(context_index >= 0); | 474 DCHECK(context_index >= 0); |
474 arguments->set_the_hole(index); | 475 arguments->set_the_hole(index); |
475 parameter_map->set( | 476 parameter_map->set( |
476 index + 2, | 477 index + 2, |
477 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); | 478 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); |
478 } | 479 } |
479 | 480 |
480 --index; | 481 --index; |
481 } | 482 } |
482 } else { | 483 } else { |
483 // If there is no aliasing, the arguments object elements are not | 484 // If there is no aliasing, the arguments object elements are not |
484 // special in any way. | 485 // special in any way. |
485 Handle<FixedArray> elements = | 486 Handle<FixedArray> elements = |
486 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); | 487 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
487 result->set_elements(*elements); | 488 result->set_elements(*elements); |
488 for (int i = 0; i < argument_count; ++i) { | 489 for (int i = 0; i < argument_count; ++i) { |
489 elements->set(i, *(parameters - i - 1)); | 490 elements->set(i, parameters[i]); |
490 } | 491 } |
491 } | 492 } |
492 } | 493 } |
493 return result; | 494 return result; |
494 } | 495 } |
495 | 496 |
496 | 497 |
497 static Handle<JSObject> NewStrictArguments(Isolate* isolate, | 498 template <typename T> |
498 Handle<JSFunction> callee, | 499 Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee, |
499 Object** parameters, | 500 T parameters, int argument_count) { |
500 int argument_count) { | |
501 Handle<JSObject> result = | 501 Handle<JSObject> result = |
502 isolate->factory()->NewArgumentsObject(callee, argument_count); | 502 isolate->factory()->NewArgumentsObject(callee, argument_count); |
503 | 503 |
504 if (argument_count > 0) { | 504 if (argument_count > 0) { |
505 Handle<FixedArray> array = | 505 Handle<FixedArray> array = |
506 isolate->factory()->NewUninitializedFixedArray(argument_count); | 506 isolate->factory()->NewUninitializedFixedArray(argument_count); |
507 DisallowHeapAllocation no_gc; | 507 DisallowHeapAllocation no_gc; |
508 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); | 508 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); |
509 for (int i = 0; i < argument_count; i++) { | 509 for (int i = 0; i < argument_count; i++) { |
510 array->set(i, *--parameters, mode); | 510 array->set(i, parameters[i], mode); |
511 } | 511 } |
512 result->set_elements(*array); | 512 result->set_elements(*array); |
513 } | 513 } |
514 return result; | 514 return result; |
515 } | 515 } |
516 | 516 |
517 | 517 |
518 RUNTIME_FUNCTION(Runtime_NewArguments) { | 518 class HandleArguments BASE_EMBEDDED { |
| 519 public: |
| 520 explicit HandleArguments(Handle<Object>* array) : array_(array) {} |
| 521 Object* operator[](int index) { return *array_[index]; } |
| 522 |
| 523 private: |
| 524 Handle<Object>* array_; |
| 525 }; |
| 526 |
| 527 |
| 528 class ParameterArguments BASE_EMBEDDED { |
| 529 public: |
| 530 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {} |
| 531 Object*& operator[](int index) { return *(parameters_ - index - 1); } |
| 532 |
| 533 private: |
| 534 Object** parameters_; |
| 535 }; |
| 536 |
| 537 } // namespace |
| 538 |
| 539 |
| 540 RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) { |
519 HandleScope scope(isolate); | 541 HandleScope scope(isolate); |
520 DCHECK(args.length() == 1); | 542 DCHECK(args.length() == 1); |
521 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); | 543 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); |
522 JavaScriptFrameIterator it(isolate); | 544 // This generic runtime function can also be used when the caller has been |
523 | 545 // inlined, we use the slow but accurate {Runtime::GetCallerArguments}. |
524 // Find the frame that holds the actual arguments passed to the function. | 546 int argument_count = 0; |
525 it.AdvanceToArgumentsFrame(); | 547 base::SmartArrayPointer<Handle<Object>> arguments = |
526 JavaScriptFrame* frame = it.frame(); | 548 Runtime::GetCallerArguments(isolate, 0, &argument_count); |
527 | 549 HandleArguments argument_getter(arguments.get()); |
528 // Determine parameter location on the stack and dispatch on language mode. | 550 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); |
529 int argument_count = frame->GetArgumentsLength(); | |
530 Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1)); | |
531 | |
532 return (is_strict(callee->shared()->language_mode()) || | |
533 !callee->has_simple_parameters()) | |
534 ? *NewStrictArguments(isolate, callee, parameters, argument_count) | |
535 : *NewSloppyArguments(isolate, callee, parameters, argument_count); | |
536 } | 551 } |
537 | 552 |
538 | 553 |
| 554 RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) { |
| 555 HandleScope scope(isolate); |
| 556 DCHECK(args.length() == 1); |
| 557 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); |
| 558 // This generic runtime function can also be used when the caller has been |
| 559 // inlined, we use the slow but accurate {Runtime::GetCallerArguments}. |
| 560 int argument_count = 0; |
| 561 base::SmartArrayPointer<Handle<Object>> arguments = |
| 562 Runtime::GetCallerArguments(isolate, 0, &argument_count); |
| 563 HandleArguments argument_getter(arguments.get()); |
| 564 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); |
| 565 } |
| 566 |
| 567 |
539 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { | 568 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { |
540 HandleScope scope(isolate); | 569 HandleScope scope(isolate); |
541 DCHECK(args.length() == 3); | 570 DCHECK(args.length() == 3); |
542 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); | 571 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); |
543 Object** parameters = reinterpret_cast<Object**>(args[1]); | 572 Object** parameters = reinterpret_cast<Object**>(args[1]); |
544 CONVERT_SMI_ARG_CHECKED(argument_count, 2); | 573 CONVERT_SMI_ARG_CHECKED(argument_count, 2); |
545 #ifdef DEBUG | 574 #ifdef DEBUG |
546 // This runtime function does not materialize the correct arguments when the | 575 // This runtime function does not materialize the correct arguments when the |
547 // caller has been inlined, better make sure we are not hitting that case. | 576 // caller has been inlined, better make sure we are not hitting that case. |
548 JavaScriptFrameIterator it(isolate); | 577 JavaScriptFrameIterator it(isolate); |
549 DCHECK(!it.frame()->HasInlinedFrames()); | 578 DCHECK(!it.frame()->HasInlinedFrames()); |
550 #endif // DEBUG | 579 #endif // DEBUG |
551 return *NewSloppyArguments(isolate, callee, parameters, argument_count); | 580 ParameterArguments argument_getter(parameters); |
| 581 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); |
552 } | 582 } |
553 | 583 |
554 | 584 |
555 RUNTIME_FUNCTION(Runtime_NewStrictArguments) { | 585 RUNTIME_FUNCTION(Runtime_NewStrictArguments) { |
556 HandleScope scope(isolate); | 586 HandleScope scope(isolate); |
557 DCHECK(args.length() == 3); | 587 DCHECK(args.length() == 3); |
558 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) | 588 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) |
559 Object** parameters = reinterpret_cast<Object**>(args[1]); | 589 Object** parameters = reinterpret_cast<Object**>(args[1]); |
560 CONVERT_SMI_ARG_CHECKED(argument_count, 2); | 590 CONVERT_SMI_ARG_CHECKED(argument_count, 2); |
561 #ifdef DEBUG | 591 #ifdef DEBUG |
562 // This runtime function does not materialize the correct arguments when the | 592 // This runtime function does not materialize the correct arguments when the |
563 // caller has been inlined, better make sure we are not hitting that case. | 593 // caller has been inlined, better make sure we are not hitting that case. |
564 JavaScriptFrameIterator it(isolate); | 594 JavaScriptFrameIterator it(isolate); |
565 DCHECK(!it.frame()->HasInlinedFrames()); | 595 DCHECK(!it.frame()->HasInlinedFrames()); |
566 #endif // DEBUG | 596 #endif // DEBUG |
567 return *NewStrictArguments(isolate, callee, parameters, argument_count); | 597 ParameterArguments argument_getter(parameters); |
| 598 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); |
568 } | 599 } |
569 | 600 |
570 | 601 |
571 RUNTIME_FUNCTION(Runtime_NewClosure) { | 602 RUNTIME_FUNCTION(Runtime_NewClosure) { |
572 HandleScope scope(isolate); | 603 HandleScope scope(isolate); |
573 DCHECK_EQ(1, args.length()); | 604 DCHECK_EQ(1, args.length()); |
574 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); | 605 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); |
575 Handle<Context> context(isolate->context(), isolate); | 606 Handle<Context> context(isolate->context(), isolate); |
576 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, | 607 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, |
577 NOT_TENURED); | 608 NOT_TENURED); |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 | 1161 |
1131 // Lookup in the initial Object.prototype object. | 1162 // Lookup in the initial Object.prototype object. |
1132 Handle<Object> result; | 1163 Handle<Object> result; |
1133 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1164 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
1134 isolate, result, | 1165 isolate, result, |
1135 Object::GetProperty(isolate->initial_object_prototype(), key)); | 1166 Object::GetProperty(isolate->initial_object_prototype(), key)); |
1136 return *result; | 1167 return *result; |
1137 } | 1168 } |
1138 } // namespace internal | 1169 } // namespace internal |
1139 } // namespace v8 | 1170 } // namespace v8 |
OLD | NEW |