OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 14670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14681 } else { | 14681 } else { |
14682 access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) && | 14682 access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) && |
14683 isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS); | 14683 isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS); |
14684 } | 14684 } |
14685 return isolate->heap()->ToBoolean(access_allowed); | 14685 return isolate->heap()->ToBoolean(access_allowed); |
14686 } | 14686 } |
14687 | 14687 |
14688 | 14688 |
14689 static MaybeObject* ArrayConstructorCommon(Isolate* isolate, | 14689 static MaybeObject* ArrayConstructorCommon(Isolate* isolate, |
14690 Handle<JSFunction> constructor, | 14690 Handle<JSFunction> constructor, |
14691 Handle<Object> type_info, | 14691 Handle<AllocationSite> site, |
14692 Arguments* caller_args) { | 14692 Arguments* caller_args) { |
14693 bool holey = false; | 14693 bool holey = false; |
14694 bool can_use_type_feedback = true; | 14694 bool can_use_type_feedback = true; |
14695 if (caller_args->length() == 1) { | 14695 if (caller_args->length() == 1) { |
14696 Object* argument_one = (*caller_args)[0]; | 14696 Object* argument_one = (*caller_args)[0]; |
14697 if (argument_one->IsSmi()) { | 14697 if (argument_one->IsSmi()) { |
14698 int value = Smi::cast(argument_one)->value(); | 14698 int value = Smi::cast(argument_one)->value(); |
14699 if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) { | 14699 if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) { |
14700 // the array is a dictionary in this case. | 14700 // the array is a dictionary in this case. |
14701 can_use_type_feedback = false; | 14701 can_use_type_feedback = false; |
14702 } else if (value != 0) { | 14702 } else if (value != 0) { |
14703 holey = true; | 14703 holey = true; |
14704 } | 14704 } |
14705 } else { | 14705 } else { |
14706 // Non-smi length argument produces a dictionary | 14706 // Non-smi length argument produces a dictionary |
14707 can_use_type_feedback = false; | 14707 can_use_type_feedback = false; |
14708 } | 14708 } |
14709 } | 14709 } |
14710 | 14710 |
14711 JSArray* array; | 14711 JSArray* array; |
14712 MaybeObject* maybe_array; | 14712 MaybeObject* maybe_array; |
14713 if (!type_info.is_null() && | 14713 if (!site.is_null() && can_use_type_feedback) { |
14714 *type_info != isolate->heap()->undefined_value() && | |
14715 Cell::cast(*type_info)->value()->IsAllocationSite() && | |
14716 can_use_type_feedback) { | |
14717 Handle<Cell> cell = Handle<Cell>::cast(type_info); | |
14718 Handle<AllocationSite> site = Handle<AllocationSite>( | |
14719 AllocationSite::cast(cell->value()), isolate); | |
14720 ASSERT(!site->SitePointsToLiteral()); | |
14721 ElementsKind to_kind = site->GetElementsKind(); | 14714 ElementsKind to_kind = site->GetElementsKind(); |
14722 if (holey && !IsFastHoleyElementsKind(to_kind)) { | 14715 if (holey && !IsFastHoleyElementsKind(to_kind)) { |
14723 to_kind = GetHoleyElementsKind(to_kind); | 14716 to_kind = GetHoleyElementsKind(to_kind); |
14724 // Update the allocation site info to reflect the advice alteration. | 14717 // Update the allocation site info to reflect the advice alteration. |
14725 site->SetElementsKind(to_kind); | 14718 site->SetElementsKind(to_kind); |
14726 } | 14719 } |
14727 | 14720 |
14728 maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite( | 14721 maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite( |
14729 *constructor, site); | 14722 *constructor, site); |
14730 if (!maybe_array->To(&array)) return maybe_array; | 14723 if (!maybe_array->To(&array)) return maybe_array; |
14731 } else { | 14724 } else { |
14732 maybe_array = isolate->heap()->AllocateJSObject(*constructor); | 14725 maybe_array = isolate->heap()->AllocateJSObject(*constructor); |
14733 if (!maybe_array->To(&array)) return maybe_array; | 14726 if (!maybe_array->To(&array)) return maybe_array; |
14734 // We might need to transition to holey | 14727 // We might need to transition to holey |
14735 ElementsKind kind = constructor->initial_map()->elements_kind(); | 14728 ElementsKind kind = constructor->initial_map()->elements_kind(); |
14736 if (holey && !IsFastHoleyElementsKind(kind)) { | 14729 if (holey && !IsFastHoleyElementsKind(kind)) { |
14737 kind = GetHoleyElementsKind(kind); | 14730 kind = GetHoleyElementsKind(kind); |
14738 maybe_array = array->TransitionElementsKind(kind); | 14731 maybe_array = array->TransitionElementsKind(kind); |
14739 if (maybe_array->IsFailure()) return maybe_array; | 14732 if (maybe_array->IsFailure()) return maybe_array; |
14740 } | 14733 } |
14741 } | 14734 } |
14742 | 14735 |
14743 maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0, | 14736 maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0, |
14744 DONT_INITIALIZE_ARRAY_ELEMENTS); | 14737 DONT_INITIALIZE_ARRAY_ELEMENTS); |
14745 if (maybe_array->IsFailure()) return maybe_array; | 14738 if (maybe_array->IsFailure()) return maybe_array; |
| 14739 ElementsKind old_kind = array->GetElementsKind(); |
14746 maybe_array = ArrayConstructInitializeElements(array, caller_args); | 14740 maybe_array = ArrayConstructInitializeElements(array, caller_args); |
14747 if (maybe_array->IsFailure()) return maybe_array; | 14741 if (maybe_array->IsFailure()) return maybe_array; |
| 14742 if (!site.is_null() && |
| 14743 (old_kind != array->GetElementsKind() || |
| 14744 !can_use_type_feedback)) { |
| 14745 // The arguments passed in caused a transition. This kind of complexity |
| 14746 // can't be dealt with in the inlined hydrogen array constructor case. |
| 14747 // We must mark the allocationsite as un-inlinable. |
| 14748 site->SetDoNotInlineCall(); |
| 14749 } |
14748 return array; | 14750 return array; |
14749 } | 14751 } |
14750 | 14752 |
14751 | 14753 |
14752 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) { | 14754 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) { |
14753 HandleScope scope(isolate); | 14755 HandleScope scope(isolate); |
14754 // If we get 2 arguments then they are the stub parameters (constructor, type | 14756 // If we get 2 arguments then they are the stub parameters (constructor, type |
14755 // info). If we get 4, then the first one is a pointer to the arguments | 14757 // info). If we get 4, then the first one is a pointer to the arguments |
14756 // passed by the caller, and the last one is the length of the arguments | 14758 // passed by the caller, and the last one is the length of the arguments |
14757 // passed to the caller (redundant, but useful to check on the deoptimizer | 14759 // passed to the caller (redundant, but useful to check on the deoptimizer |
14758 // with an assert). | 14760 // with an assert). |
14759 Arguments empty_args(0, NULL); | 14761 Arguments empty_args(0, NULL); |
14760 bool no_caller_args = args.length() == 2; | 14762 bool no_caller_args = args.length() == 2; |
14761 ASSERT(no_caller_args || args.length() == 4); | 14763 ASSERT(no_caller_args || args.length() == 4); |
14762 int parameters_start = no_caller_args ? 0 : 1; | 14764 int parameters_start = no_caller_args ? 0 : 1; |
14763 Arguments* caller_args = no_caller_args | 14765 Arguments* caller_args = no_caller_args |
14764 ? &empty_args | 14766 ? &empty_args |
14765 : reinterpret_cast<Arguments*>(args[0]); | 14767 : reinterpret_cast<Arguments*>(args[0]); |
14766 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start); | 14768 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start); |
14767 CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1); | 14769 CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1); |
14768 #ifdef DEBUG | 14770 #ifdef DEBUG |
14769 if (!no_caller_args) { | 14771 if (!no_caller_args) { |
14770 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2); | 14772 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2); |
14771 ASSERT(arg_count == caller_args->length()); | 14773 ASSERT(arg_count == caller_args->length()); |
14772 } | 14774 } |
14773 #endif | 14775 #endif |
| 14776 |
| 14777 Handle<AllocationSite> site; |
| 14778 if (!type_info.is_null() && |
| 14779 *type_info != isolate->heap()->undefined_value() && |
| 14780 Cell::cast(*type_info)->value()->IsAllocationSite()) { |
| 14781 site = Handle<AllocationSite>( |
| 14782 AllocationSite::cast(Cell::cast(*type_info)->value()), isolate); |
| 14783 ASSERT(!site->SitePointsToLiteral()); |
| 14784 } |
| 14785 |
14774 return ArrayConstructorCommon(isolate, | 14786 return ArrayConstructorCommon(isolate, |
14775 constructor, | 14787 constructor, |
14776 type_info, | 14788 site, |
14777 caller_args); | 14789 caller_args); |
14778 } | 14790 } |
14779 | 14791 |
14780 | 14792 |
14781 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) { | 14793 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) { |
14782 HandleScope scope(isolate); | 14794 HandleScope scope(isolate); |
14783 Arguments empty_args(0, NULL); | 14795 Arguments empty_args(0, NULL); |
14784 bool no_caller_args = args.length() == 1; | 14796 bool no_caller_args = args.length() == 1; |
14785 ASSERT(no_caller_args || args.length() == 3); | 14797 ASSERT(no_caller_args || args.length() == 3); |
14786 int parameters_start = no_caller_args ? 0 : 1; | 14798 int parameters_start = no_caller_args ? 0 : 1; |
14787 Arguments* caller_args = no_caller_args | 14799 Arguments* caller_args = no_caller_args |
14788 ? &empty_args | 14800 ? &empty_args |
14789 : reinterpret_cast<Arguments*>(args[0]); | 14801 : reinterpret_cast<Arguments*>(args[0]); |
14790 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start); | 14802 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start); |
14791 #ifdef DEBUG | 14803 #ifdef DEBUG |
14792 if (!no_caller_args) { | 14804 if (!no_caller_args) { |
14793 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1); | 14805 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1); |
14794 ASSERT(arg_count == caller_args->length()); | 14806 ASSERT(arg_count == caller_args->length()); |
14795 } | 14807 } |
14796 #endif | 14808 #endif |
14797 return ArrayConstructorCommon(isolate, | 14809 return ArrayConstructorCommon(isolate, |
14798 constructor, | 14810 constructor, |
14799 Handle<Object>::null(), | 14811 Handle<AllocationSite>::null(), |
14800 caller_args); | 14812 caller_args); |
14801 } | 14813 } |
14802 | 14814 |
14803 | 14815 |
14804 // ---------------------------------------------------------------------------- | 14816 // ---------------------------------------------------------------------------- |
14805 // Implementation of Runtime | 14817 // Implementation of Runtime |
14806 | 14818 |
14807 #define F(name, number_of_args, result_size) \ | 14819 #define F(name, number_of_args, result_size) \ |
14808 { Runtime::k##name, Runtime::RUNTIME, #name, \ | 14820 { Runtime::k##name, Runtime::RUNTIME, #name, \ |
14809 FUNCTION_ADDR(Runtime_##name), number_of_args, result_size }, | 14821 FUNCTION_ADDR(Runtime_##name), number_of_args, result_size }, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14878 // Handle last resort GC and make sure to allow future allocations | 14890 // Handle last resort GC and make sure to allow future allocations |
14879 // to grow the heap without causing GCs (if possible). | 14891 // to grow the heap without causing GCs (if possible). |
14880 isolate->counters()->gc_last_resort_from_js()->Increment(); | 14892 isolate->counters()->gc_last_resort_from_js()->Increment(); |
14881 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 14893 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
14882 "Runtime::PerformGC"); | 14894 "Runtime::PerformGC"); |
14883 } | 14895 } |
14884 } | 14896 } |
14885 | 14897 |
14886 | 14898 |
14887 } } // namespace v8::internal | 14899 } } // namespace v8::internal |
OLD | NEW |