| 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 1560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value)); | 1571 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value)); |
| 1572 } | 1572 } |
| 1573 | 1573 |
| 1574 | 1574 |
| 1575 // --- S c r i p t D a t a --- | 1575 // --- S c r i p t D a t a --- |
| 1576 | 1576 |
| 1577 | 1577 |
| 1578 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) { | 1578 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) { |
| 1579 i::Handle<i::String> str = Utils::OpenHandle(*source); | 1579 i::Handle<i::String> str = Utils::OpenHandle(*source); |
| 1580 i::Isolate* isolate = str->GetIsolate(); | 1580 i::Isolate* isolate = str->GetIsolate(); |
| 1581 return i::PreParserApi::PreParse(isolate, str); | 1581 if (str->IsExternalTwoByteString()) { |
| 1582 i::ExternalTwoByteStringUtf16CharacterStream stream( |
| 1583 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length()); |
| 1584 return i::PreParserApi::PreParse(isolate, &stream); |
| 1585 } else { |
| 1586 i::GenericStringUtf16CharacterStream stream(str, 0, str->length()); |
| 1587 return i::PreParserApi::PreParse(isolate, &stream); |
| 1588 } |
| 1582 } | 1589 } |
| 1583 | 1590 |
| 1584 | 1591 |
| 1585 ScriptData* ScriptData::New(const char* data, int length) { | 1592 ScriptData* ScriptData::New(const char* data, int length) { |
| 1586 // Return an empty ScriptData if the length is obviously invalid. | 1593 // Return an empty ScriptData if the length is obviously invalid. |
| 1587 if (length % sizeof(unsigned) != 0) { | 1594 if (length % sizeof(unsigned) != 0) { |
| 1588 return new i::ScriptDataImpl(); | 1595 return new i::ScriptDataImpl(); |
| 1589 } | 1596 } |
| 1590 | 1597 |
| 1591 // Copy the data to ensure it is properly aligned. | 1598 // Copy the data to ensure it is properly aligned. |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2357 bool Value::IsArrayBufferView() const { | 2364 bool Value::IsArrayBufferView() const { |
| 2358 return Utils::OpenHandle(this)->IsJSArrayBufferView(); | 2365 return Utils::OpenHandle(this)->IsJSArrayBufferView(); |
| 2359 } | 2366 } |
| 2360 | 2367 |
| 2361 | 2368 |
| 2362 bool Value::IsTypedArray() const { | 2369 bool Value::IsTypedArray() const { |
| 2363 return Utils::OpenHandle(this)->IsJSTypedArray(); | 2370 return Utils::OpenHandle(this)->IsJSTypedArray(); |
| 2364 } | 2371 } |
| 2365 | 2372 |
| 2366 | 2373 |
| 2367 #define TYPED_ARRAY_LIST(F) \ | 2374 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ |
| 2368 F(Uint8Array, kExternalUnsignedByteArray) \ | 2375 bool Value::Is##Type##Array() const { \ |
| 2369 F(Int8Array, kExternalByteArray) \ | 2376 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ |
| 2370 F(Uint16Array, kExternalUnsignedShortArray) \ | 2377 return obj->IsJSTypedArray() && \ |
| 2371 F(Int16Array, kExternalShortArray) \ | 2378 i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array; \ |
| 2372 F(Uint32Array, kExternalUnsignedIntArray) \ | |
| 2373 F(Int32Array, kExternalIntArray) \ | |
| 2374 F(Float32Array, kExternalFloatArray) \ | |
| 2375 F(Float64Array, kExternalDoubleArray) \ | |
| 2376 F(Uint8ClampedArray, kExternalPixelArray) | |
| 2377 | |
| 2378 | |
| 2379 #define VALUE_IS_TYPED_ARRAY(TypedArray, type_const) \ | |
| 2380 bool Value::Is##TypedArray() const { \ | |
| 2381 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ | |
| 2382 if (!obj->IsJSTypedArray()) return false; \ | |
| 2383 return i::JSTypedArray::cast(*obj)->type() == type_const; \ | |
| 2384 } | 2379 } |
| 2385 | 2380 |
| 2386 TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY) | 2381 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY) |
| 2387 | 2382 |
| 2388 #undef VALUE_IS_TYPED_ARRAY | 2383 #undef VALUE_IS_TYPED_ARRAY |
| 2389 | 2384 |
| 2390 | 2385 |
| 2391 bool Value::IsDataView() const { | 2386 bool Value::IsDataView() const { |
| 2392 return Utils::OpenHandle(this)->IsJSDataView(); | 2387 return Utils::OpenHandle(this)->IsJSDataView(); |
| 2393 } | 2388 } |
| 2394 | 2389 |
| 2395 | 2390 |
| 2396 bool Value::IsObject() const { | 2391 bool Value::IsObject() const { |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2708 | 2703 |
| 2709 | 2704 |
| 2710 void v8::TypedArray::CheckCast(Value* that) { | 2705 void v8::TypedArray::CheckCast(Value* that) { |
| 2711 i::Handle<i::Object> obj = Utils::OpenHandle(that); | 2706 i::Handle<i::Object> obj = Utils::OpenHandle(that); |
| 2712 Utils::ApiCheck(obj->IsJSTypedArray(), | 2707 Utils::ApiCheck(obj->IsJSTypedArray(), |
| 2713 "v8::TypedArray::Cast()", | 2708 "v8::TypedArray::Cast()", |
| 2714 "Could not convert to TypedArray"); | 2709 "Could not convert to TypedArray"); |
| 2715 } | 2710 } |
| 2716 | 2711 |
| 2717 | 2712 |
| 2718 #define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \ | 2713 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size) \ |
| 2719 void v8::ApiClass::CheckCast(Value* that) { \ | 2714 void v8::Type##Array::CheckCast(Value* that) { \ |
| 2720 i::Handle<i::Object> obj = Utils::OpenHandle(that); \ | 2715 i::Handle<i::Object> obj = Utils::OpenHandle(that); \ |
| 2721 Utils::ApiCheck(obj->IsJSTypedArray() && \ | 2716 Utils::ApiCheck(obj->IsJSTypedArray() && \ |
| 2722 i::JSTypedArray::cast(*obj)->type() == typeConst, \ | 2717 i::JSTypedArray::cast(*obj)->type() == \ |
| 2723 "v8::" #ApiClass "::Cast()", \ | 2718 kExternal##Type##Array, \ |
| 2724 "Could not convert to " #ApiClass); \ | 2719 "v8::" #Type "Array::Cast()", \ |
| 2720 "Could not convert to " #Type "Array"); \ |
| 2725 } | 2721 } |
| 2726 | 2722 |
| 2727 | 2723 |
| 2728 TYPED_ARRAY_LIST(CHECK_TYPED_ARRAY_CAST) | 2724 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST) |
| 2729 | 2725 |
| 2730 #undef CHECK_TYPED_ARRAY_CAST | 2726 #undef CHECK_TYPED_ARRAY_CAST |
| 2731 | 2727 |
| 2732 | 2728 |
| 2733 void v8::DataView::CheckCast(Value* that) { | 2729 void v8::DataView::CheckCast(Value* that) { |
| 2734 i::Handle<i::Object> obj = Utils::OpenHandle(that); | 2730 i::Handle<i::Object> obj = Utils::OpenHandle(that); |
| 2735 Utils::ApiCheck(obj->IsJSDataView(), | 2731 Utils::ApiCheck(obj->IsJSDataView(), |
| 2736 "v8::DataView::Cast()", | 2732 "v8::DataView::Cast()", |
| 2737 "Could not convert to DataView"); | 2733 "Could not convert to DataView"); |
| 2738 } | 2734 } |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3651 i::JSObject::DeleteHiddenProperty(self, key_string); | 3647 i::JSObject::DeleteHiddenProperty(self, key_string); |
| 3652 return true; | 3648 return true; |
| 3653 } | 3649 } |
| 3654 | 3650 |
| 3655 | 3651 |
| 3656 namespace { | 3652 namespace { |
| 3657 | 3653 |
| 3658 static i::ElementsKind GetElementsKindFromExternalArrayType( | 3654 static i::ElementsKind GetElementsKindFromExternalArrayType( |
| 3659 ExternalArrayType array_type) { | 3655 ExternalArrayType array_type) { |
| 3660 switch (array_type) { | 3656 switch (array_type) { |
| 3661 case kExternalByteArray: | 3657 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \ |
| 3662 return i::EXTERNAL_BYTE_ELEMENTS; | 3658 case kExternal##Type##Array: \ |
| 3663 break; | 3659 return i::EXTERNAL_##TYPE##_ELEMENTS; |
| 3664 case kExternalUnsignedByteArray: | 3660 |
| 3665 return i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS; | 3661 TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND) |
| 3666 break; | 3662 #undef ARRAY_TYPE_TO_ELEMENTS_KIND |
| 3667 case kExternalShortArray: | |
| 3668 return i::EXTERNAL_SHORT_ELEMENTS; | |
| 3669 break; | |
| 3670 case kExternalUnsignedShortArray: | |
| 3671 return i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS; | |
| 3672 break; | |
| 3673 case kExternalIntArray: | |
| 3674 return i::EXTERNAL_INT_ELEMENTS; | |
| 3675 break; | |
| 3676 case kExternalUnsignedIntArray: | |
| 3677 return i::EXTERNAL_UNSIGNED_INT_ELEMENTS; | |
| 3678 break; | |
| 3679 case kExternalFloatArray: | |
| 3680 return i::EXTERNAL_FLOAT_ELEMENTS; | |
| 3681 break; | |
| 3682 case kExternalDoubleArray: | |
| 3683 return i::EXTERNAL_DOUBLE_ELEMENTS; | |
| 3684 break; | |
| 3685 case kExternalPixelArray: | |
| 3686 return i::EXTERNAL_PIXEL_ELEMENTS; | |
| 3687 break; | |
| 3688 } | 3663 } |
| 3689 UNREACHABLE(); | 3664 UNREACHABLE(); |
| 3690 return i::DICTIONARY_ELEMENTS; | 3665 return i::DICTIONARY_ELEMENTS; |
| 3691 } | 3666 } |
| 3692 | 3667 |
| 3693 | 3668 |
| 3694 void PrepareExternalArrayElements(i::Handle<i::JSObject> object, | 3669 void PrepareExternalArrayElements(i::Handle<i::JSObject> object, |
| 3695 void* data, | 3670 void* data, |
| 3696 ExternalArrayType array_type, | 3671 ExternalArrayType array_type, |
| 3697 int length) { | 3672 int length) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3710 | 3685 |
| 3711 } // namespace | 3686 } // namespace |
| 3712 | 3687 |
| 3713 | 3688 |
| 3714 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { | 3689 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { |
| 3715 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 3690 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
| 3716 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); | 3691 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); |
| 3717 ENTER_V8(isolate); | 3692 ENTER_V8(isolate); |
| 3718 i::HandleScope scope(isolate); | 3693 i::HandleScope scope(isolate); |
| 3719 if (!Utils::ApiCheck(length >= 0 && | 3694 if (!Utils::ApiCheck(length >= 0 && |
| 3720 length <= i::ExternalPixelArray::kMaxLength, | 3695 length <= i::ExternalUint8ClampedArray::kMaxLength, |
| 3721 "v8::Object::SetIndexedPropertiesToPixelData()", | 3696 "v8::Object::SetIndexedPropertiesToPixelData()", |
| 3722 "length exceeds max acceptable value")) { | 3697 "length exceeds max acceptable value")) { |
| 3723 return; | 3698 return; |
| 3724 } | 3699 } |
| 3725 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3700 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3726 if (!Utils::ApiCheck(!self->IsJSArray(), | 3701 if (!Utils::ApiCheck(!self->IsJSArray(), |
| 3727 "v8::Object::SetIndexedPropertiesToPixelData()", | 3702 "v8::Object::SetIndexedPropertiesToPixelData()", |
| 3728 "JSArray is not supported")) { | 3703 "JSArray is not supported")) { |
| 3729 return; | 3704 return; |
| 3730 } | 3705 } |
| 3731 PrepareExternalArrayElements(self, data, kExternalPixelArray, length); | 3706 PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length); |
| 3732 } | 3707 } |
| 3733 | 3708 |
| 3734 | 3709 |
| 3735 bool v8::Object::HasIndexedPropertiesInPixelData() { | 3710 bool v8::Object::HasIndexedPropertiesInPixelData() { |
| 3736 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3711 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3737 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()", | 3712 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()", |
| 3738 return false); | 3713 return false); |
| 3739 return self->HasExternalPixelElements(); | 3714 return self->HasExternalUint8ClampedElements(); |
| 3740 } | 3715 } |
| 3741 | 3716 |
| 3742 | 3717 |
| 3743 uint8_t* v8::Object::GetIndexedPropertiesPixelData() { | 3718 uint8_t* v8::Object::GetIndexedPropertiesPixelData() { |
| 3744 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3719 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3745 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()", | 3720 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()", |
| 3746 return NULL); | 3721 return NULL); |
| 3747 if (self->HasExternalPixelElements()) { | 3722 if (self->HasExternalUint8ClampedElements()) { |
| 3748 return i::ExternalPixelArray::cast(self->elements())-> | 3723 return i::ExternalUint8ClampedArray::cast(self->elements())-> |
| 3749 external_pixel_pointer(); | 3724 external_uint8_clamped_pointer(); |
| 3750 } else { | 3725 } else { |
| 3751 return NULL; | 3726 return NULL; |
| 3752 } | 3727 } |
| 3753 } | 3728 } |
| 3754 | 3729 |
| 3755 | 3730 |
| 3756 int v8::Object::GetIndexedPropertiesPixelDataLength() { | 3731 int v8::Object::GetIndexedPropertiesPixelDataLength() { |
| 3757 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3732 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3758 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()", | 3733 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()", |
| 3759 return -1); | 3734 return -1); |
| 3760 if (self->HasExternalPixelElements()) { | 3735 if (self->HasExternalUint8ClampedElements()) { |
| 3761 return i::ExternalPixelArray::cast(self->elements())->length(); | 3736 return i::ExternalUint8ClampedArray::cast(self->elements())->length(); |
| 3762 } else { | 3737 } else { |
| 3763 return -1; | 3738 return -1; |
| 3764 } | 3739 } |
| 3765 } | 3740 } |
| 3766 | 3741 |
| 3767 | 3742 |
| 3768 void v8::Object::SetIndexedPropertiesToExternalArrayData( | 3743 void v8::Object::SetIndexedPropertiesToExternalArrayData( |
| 3769 void* data, | 3744 void* data, |
| 3770 ExternalArrayType array_type, | 3745 ExternalArrayType array_type, |
| 3771 int length) { | 3746 int length) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3809 } | 3784 } |
| 3810 } | 3785 } |
| 3811 | 3786 |
| 3812 | 3787 |
| 3813 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() { | 3788 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() { |
| 3814 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3789 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3815 ON_BAILOUT(self->GetIsolate(), | 3790 ON_BAILOUT(self->GetIsolate(), |
| 3816 "v8::GetIndexedPropertiesExternalArrayDataType()", | 3791 "v8::GetIndexedPropertiesExternalArrayDataType()", |
| 3817 return static_cast<ExternalArrayType>(-1)); | 3792 return static_cast<ExternalArrayType>(-1)); |
| 3818 switch (self->elements()->map()->instance_type()) { | 3793 switch (self->elements()->map()->instance_type()) { |
| 3819 case i::EXTERNAL_BYTE_ARRAY_TYPE: | 3794 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \ |
| 3820 return kExternalByteArray; | 3795 case i::EXTERNAL_##TYPE##_ARRAY_TYPE: \ |
| 3821 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 3796 return kExternal##Type##Array; |
| 3822 return kExternalUnsignedByteArray; | 3797 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE) |
| 3823 case i::EXTERNAL_SHORT_ARRAY_TYPE: | 3798 #undef INSTANCE_TYPE_TO_ARRAY_TYPE |
| 3824 return kExternalShortArray; | |
| 3825 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | |
| 3826 return kExternalUnsignedShortArray; | |
| 3827 case i::EXTERNAL_INT_ARRAY_TYPE: | |
| 3828 return kExternalIntArray; | |
| 3829 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: | |
| 3830 return kExternalUnsignedIntArray; | |
| 3831 case i::EXTERNAL_FLOAT_ARRAY_TYPE: | |
| 3832 return kExternalFloatArray; | |
| 3833 case i::EXTERNAL_DOUBLE_ARRAY_TYPE: | |
| 3834 return kExternalDoubleArray; | |
| 3835 case i::EXTERNAL_PIXEL_ARRAY_TYPE: | |
| 3836 return kExternalPixelArray; | |
| 3837 default: | 3799 default: |
| 3838 return static_cast<ExternalArrayType>(-1); | 3800 return static_cast<ExternalArrayType>(-1); |
| 3839 } | 3801 } |
| 3840 } | 3802 } |
| 3841 | 3803 |
| 3842 | 3804 |
| 3843 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { | 3805 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { |
| 3844 i::Handle<i::JSObject> self = Utils::OpenHandle(this); | 3806 i::Handle<i::JSObject> self = Utils::OpenHandle(this); |
| 3845 ON_BAILOUT(self->GetIsolate(), | 3807 ON_BAILOUT(self->GetIsolate(), |
| 3846 "v8::GetIndexedPropertiesExternalArrayDataLength()", | 3808 "v8::GetIndexedPropertiesExternalArrayDataLength()", |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4440 int String::Utf8Length() const { | 4402 int String::Utf8Length() const { |
| 4441 i::Handle<i::String> str = Utils::OpenHandle(this); | 4403 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4442 i::Isolate* isolate = str->GetIsolate(); | 4404 i::Isolate* isolate = str->GetIsolate(); |
| 4443 return v8::Utf8Length(*str, isolate); | 4405 return v8::Utf8Length(*str, isolate); |
| 4444 } | 4406 } |
| 4445 | 4407 |
| 4446 | 4408 |
| 4447 class Utf8WriterVisitor { | 4409 class Utf8WriterVisitor { |
| 4448 public: | 4410 public: |
| 4449 Utf8WriterVisitor( | 4411 Utf8WriterVisitor( |
| 4450 char* buffer, int capacity, bool skip_capacity_check) | 4412 char* buffer, |
| 4451 : early_termination_(false), | 4413 int capacity, |
| 4452 last_character_(unibrow::Utf16::kNoPreviousCharacter), | 4414 bool skip_capacity_check, |
| 4453 buffer_(buffer), | 4415 bool replace_invalid_utf8) |
| 4454 start_(buffer), | 4416 : early_termination_(false), |
| 4455 capacity_(capacity), | 4417 last_character_(unibrow::Utf16::kNoPreviousCharacter), |
| 4456 skip_capacity_check_(capacity == -1 || skip_capacity_check), | 4418 buffer_(buffer), |
| 4457 utf16_chars_read_(0) { | 4419 start_(buffer), |
| 4420 capacity_(capacity), |
| 4421 skip_capacity_check_(capacity == -1 || skip_capacity_check), |
| 4422 replace_invalid_utf8_(replace_invalid_utf8), |
| 4423 utf16_chars_read_(0) { |
| 4458 } | 4424 } |
| 4459 | 4425 |
| 4460 static int WriteEndCharacter(uint16_t character, | 4426 static int WriteEndCharacter(uint16_t character, |
| 4461 int last_character, | 4427 int last_character, |
| 4462 int remaining, | 4428 int remaining, |
| 4463 char* const buffer) { | 4429 char* const buffer, |
| 4430 bool replace_invalid_utf8) { |
| 4464 using namespace unibrow; | 4431 using namespace unibrow; |
| 4465 ASSERT(remaining > 0); | 4432 ASSERT(remaining > 0); |
| 4466 // We can't use a local buffer here because Encode needs to modify | 4433 // We can't use a local buffer here because Encode needs to modify |
| 4467 // previous characters in the stream. We know, however, that | 4434 // previous characters in the stream. We know, however, that |
| 4468 // exactly one character will be advanced. | 4435 // exactly one character will be advanced. |
| 4469 if (Utf16::IsTrailSurrogate(character) && | 4436 if (Utf16::IsSurrogatePair(last_character, character)) { |
| 4470 Utf16::IsLeadSurrogate(last_character)) { | 4437 int written = Utf8::Encode(buffer, |
| 4471 int written = Utf8::Encode(buffer, character, last_character); | 4438 character, |
| 4439 last_character, |
| 4440 replace_invalid_utf8); |
| 4472 ASSERT(written == 1); | 4441 ASSERT(written == 1); |
| 4473 return written; | 4442 return written; |
| 4474 } | 4443 } |
| 4475 // Use a scratch buffer to check the required characters. | 4444 // Use a scratch buffer to check the required characters. |
| 4476 char temp_buffer[Utf8::kMaxEncodedSize]; | 4445 char temp_buffer[Utf8::kMaxEncodedSize]; |
| 4477 // Can't encode using last_character as gcc has array bounds issues. | 4446 // Can't encode using last_character as gcc has array bounds issues. |
| 4478 int written = Utf8::Encode(temp_buffer, | 4447 int written = Utf8::Encode(temp_buffer, |
| 4479 character, | 4448 character, |
| 4480 Utf16::kNoPreviousCharacter); | 4449 Utf16::kNoPreviousCharacter, |
| 4450 replace_invalid_utf8); |
| 4481 // Won't fit. | 4451 // Won't fit. |
| 4482 if (written > remaining) return 0; | 4452 if (written > remaining) return 0; |
| 4483 // Copy over the character from temp_buffer. | 4453 // Copy over the character from temp_buffer. |
| 4484 for (int j = 0; j < written; j++) { | 4454 for (int j = 0; j < written; j++) { |
| 4485 buffer[j] = temp_buffer[j]; | 4455 buffer[j] = temp_buffer[j]; |
| 4486 } | 4456 } |
| 4487 return written; | 4457 return written; |
| 4488 } | 4458 } |
| 4489 | 4459 |
| 4460 // Visit writes out a group of code units (chars) of a v8::String to the |
| 4461 // internal buffer_. This is done in two phases. The first phase calculates a |
| 4462 // pesimistic estimate (writable_length) on how many code units can be safely |
| 4463 // written without exceeding the buffer capacity and without writing the last |
| 4464 // code unit (it could be a lead surrogate). The estimated number of code |
| 4465 // units is then written out in one go, and the reported byte usage is used |
| 4466 // to correct the estimate. This is repeated until the estimate becomes <= 0 |
| 4467 // or all code units have been written out. The second phase writes out code |
| 4468 // units until the buffer capacity is reached, would be exceeded by the next |
| 4469 // unit, or all units have been written out. |
| 4490 template<typename Char> | 4470 template<typename Char> |
| 4491 void Visit(const Char* chars, const int length) { | 4471 void Visit(const Char* chars, const int length) { |
| 4492 using namespace unibrow; | 4472 using namespace unibrow; |
| 4493 ASSERT(!early_termination_); | 4473 ASSERT(!early_termination_); |
| 4494 if (length == 0) return; | 4474 if (length == 0) return; |
| 4495 // Copy state to stack. | 4475 // Copy state to stack. |
| 4496 char* buffer = buffer_; | 4476 char* buffer = buffer_; |
| 4497 int last_character = | 4477 int last_character = |
| 4498 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_; | 4478 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_; |
| 4499 int i = 0; | 4479 int i = 0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4517 // Write the characters to the stream. | 4497 // Write the characters to the stream. |
| 4518 if (sizeof(Char) == 1) { | 4498 if (sizeof(Char) == 1) { |
| 4519 for (; i < fast_length; i++) { | 4499 for (; i < fast_length; i++) { |
| 4520 buffer += | 4500 buffer += |
| 4521 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++)); | 4501 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++)); |
| 4522 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); | 4502 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); |
| 4523 } | 4503 } |
| 4524 } else { | 4504 } else { |
| 4525 for (; i < fast_length; i++) { | 4505 for (; i < fast_length; i++) { |
| 4526 uint16_t character = *chars++; | 4506 uint16_t character = *chars++; |
| 4527 buffer += Utf8::Encode(buffer, character, last_character); | 4507 buffer += Utf8::Encode(buffer, |
| 4508 character, |
| 4509 last_character, |
| 4510 replace_invalid_utf8_); |
| 4528 last_character = character; | 4511 last_character = character; |
| 4529 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); | 4512 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); |
| 4530 } | 4513 } |
| 4531 } | 4514 } |
| 4532 // Array is fully written. Exit. | 4515 // Array is fully written. Exit. |
| 4533 if (fast_length == length) { | 4516 if (fast_length == length) { |
| 4534 // Write state back out to object. | 4517 // Write state back out to object. |
| 4535 last_character_ = last_character; | 4518 last_character_ = last_character; |
| 4536 buffer_ = buffer; | 4519 buffer_ = buffer; |
| 4537 utf16_chars_read_ += length; | 4520 utf16_chars_read_ += length; |
| 4538 return; | 4521 return; |
| 4539 } | 4522 } |
| 4540 } | 4523 } |
| 4541 ASSERT(!skip_capacity_check_); | 4524 ASSERT(!skip_capacity_check_); |
| 4542 // Slow loop. Must check capacity on each iteration. | 4525 // Slow loop. Must check capacity on each iteration. |
| 4543 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); | 4526 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); |
| 4544 ASSERT(remaining_capacity >= 0); | 4527 ASSERT(remaining_capacity >= 0); |
| 4545 for (; i < length && remaining_capacity > 0; i++) { | 4528 for (; i < length && remaining_capacity > 0; i++) { |
| 4546 uint16_t character = *chars++; | 4529 uint16_t character = *chars++; |
| 4530 // remaining_capacity is <= 3 bytes at this point, so we do not write out |
| 4531 // an umatched lead surrogate. |
| 4532 if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) { |
| 4533 early_termination_ = true; |
| 4534 break; |
| 4535 } |
| 4547 int written = WriteEndCharacter(character, | 4536 int written = WriteEndCharacter(character, |
| 4548 last_character, | 4537 last_character, |
| 4549 remaining_capacity, | 4538 remaining_capacity, |
| 4550 buffer); | 4539 buffer, |
| 4540 replace_invalid_utf8_); |
| 4551 if (written == 0) { | 4541 if (written == 0) { |
| 4552 early_termination_ = true; | 4542 early_termination_ = true; |
| 4553 break; | 4543 break; |
| 4554 } | 4544 } |
| 4555 buffer += written; | 4545 buffer += written; |
| 4556 remaining_capacity -= written; | 4546 remaining_capacity -= written; |
| 4557 last_character = character; | 4547 last_character = character; |
| 4558 } | 4548 } |
| 4559 // Write state back out to object. | 4549 // Write state back out to object. |
| 4560 last_character_ = last_character; | 4550 last_character_ = last_character; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4588 return static_cast<int>(buffer_ - start_); | 4578 return static_cast<int>(buffer_ - start_); |
| 4589 } | 4579 } |
| 4590 | 4580 |
| 4591 private: | 4581 private: |
| 4592 bool early_termination_; | 4582 bool early_termination_; |
| 4593 int last_character_; | 4583 int last_character_; |
| 4594 char* buffer_; | 4584 char* buffer_; |
| 4595 char* const start_; | 4585 char* const start_; |
| 4596 int capacity_; | 4586 int capacity_; |
| 4597 bool const skip_capacity_check_; | 4587 bool const skip_capacity_check_; |
| 4588 bool const replace_invalid_utf8_; |
| 4598 int utf16_chars_read_; | 4589 int utf16_chars_read_; |
| 4599 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor); | 4590 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor); |
| 4600 }; | 4591 }; |
| 4601 | 4592 |
| 4602 | 4593 |
| 4603 static bool RecursivelySerializeToUtf8(i::String* current, | 4594 static bool RecursivelySerializeToUtf8(i::String* current, |
| 4604 Utf8WriterVisitor* writer, | 4595 Utf8WriterVisitor* writer, |
| 4605 int recursion_budget) { | 4596 int recursion_budget) { |
| 4606 while (!writer->IsDone()) { | 4597 while (!writer->IsDone()) { |
| 4607 i::ConsString* cons_string = i::String::VisitFlat(writer, current); | 4598 i::ConsString* cons_string = i::String::VisitFlat(writer, current); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4626 int options) const { | 4617 int options) const { |
| 4627 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 4618 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
| 4628 LOG_API(isolate, "String::WriteUtf8"); | 4619 LOG_API(isolate, "String::WriteUtf8"); |
| 4629 ENTER_V8(isolate); | 4620 ENTER_V8(isolate); |
| 4630 i::Handle<i::String> str = Utils::OpenHandle(this); | 4621 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4631 if (options & HINT_MANY_WRITES_EXPECTED) { | 4622 if (options & HINT_MANY_WRITES_EXPECTED) { |
| 4632 FlattenString(str); // Flatten the string for efficiency. | 4623 FlattenString(str); // Flatten the string for efficiency. |
| 4633 } | 4624 } |
| 4634 const int string_length = str->length(); | 4625 const int string_length = str->length(); |
| 4635 bool write_null = !(options & NO_NULL_TERMINATION); | 4626 bool write_null = !(options & NO_NULL_TERMINATION); |
| 4627 bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8); |
| 4628 int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize; |
| 4636 // First check if we can just write the string without checking capacity. | 4629 // First check if we can just write the string without checking capacity. |
| 4637 if (capacity == -1 || capacity / 3 >= string_length) { | 4630 if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) { |
| 4638 Utf8WriterVisitor writer(buffer, capacity, true); | 4631 Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8); |
| 4639 const int kMaxRecursion = 100; | 4632 const int kMaxRecursion = 100; |
| 4640 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion); | 4633 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion); |
| 4641 if (success) return writer.CompleteWrite(write_null, nchars_ref); | 4634 if (success) return writer.CompleteWrite(write_null, nchars_ref); |
| 4642 } else if (capacity >= string_length) { | 4635 } else if (capacity >= string_length) { |
| 4643 // First check that the buffer is large enough. | 4636 // First check that the buffer is large enough. |
| 4644 int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate()); | 4637 int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate()); |
| 4645 if (utf8_bytes <= capacity) { | 4638 if (utf8_bytes <= capacity) { |
| 4646 // ASCII fast path. | 4639 // ASCII fast path. |
| 4647 if (utf8_bytes == string_length) { | 4640 if (utf8_bytes == string_length) { |
| 4648 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options); | 4641 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options); |
| 4649 if (nchars_ref != NULL) *nchars_ref = string_length; | 4642 if (nchars_ref != NULL) *nchars_ref = string_length; |
| 4650 if (write_null && (utf8_bytes+1 <= capacity)) { | 4643 if (write_null && (utf8_bytes+1 <= capacity)) { |
| 4651 return string_length + 1; | 4644 return string_length + 1; |
| 4652 } | 4645 } |
| 4653 return string_length; | 4646 return string_length; |
| 4654 } | 4647 } |
| 4655 if (write_null && (utf8_bytes+1 > capacity)) { | 4648 if (write_null && (utf8_bytes+1 > capacity)) { |
| 4656 options |= NO_NULL_TERMINATION; | 4649 options |= NO_NULL_TERMINATION; |
| 4657 } | 4650 } |
| 4658 // Recurse once without a capacity limit. | 4651 // Recurse once without a capacity limit. |
| 4659 // This will get into the first branch above. | 4652 // This will get into the first branch above. |
| 4660 // TODO(dcarney) Check max left rec. in Utf8Length and fall through. | 4653 // TODO(dcarney) Check max left rec. in Utf8Length and fall through. |
| 4661 return WriteUtf8(buffer, -1, nchars_ref, options); | 4654 return WriteUtf8(buffer, -1, nchars_ref, options); |
| 4662 } | 4655 } |
| 4663 } | 4656 } |
| 4664 // Recursive slow path can potentially be unreasonable slow. Flatten. | 4657 // Recursive slow path can potentially be unreasonable slow. Flatten. |
| 4665 str = FlattenGetString(str); | 4658 str = FlattenGetString(str); |
| 4666 Utf8WriterVisitor writer(buffer, capacity, false); | 4659 Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8); |
| 4667 i::String::VisitFlat(&writer, *str); | 4660 i::String::VisitFlat(&writer, *str); |
| 4668 return writer.CompleteWrite(write_null, nchars_ref); | 4661 return writer.CompleteWrite(write_null, nchars_ref); |
| 4669 } | 4662 } |
| 4670 | 4663 |
| 4671 | 4664 |
| 4672 template<typename CharType> | 4665 template<typename CharType> |
| 4673 static inline int WriteHelper(const String* string, | 4666 static inline int WriteHelper(const String* string, |
| 4674 CharType* buffer, | 4667 CharType* buffer, |
| 4675 int start, | 4668 int start, |
| 4676 int length, | 4669 int length, |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5426 } | 5419 } |
| 5427 | 5420 |
| 5428 | 5421 |
| 5429 static i::Handle<i::String> NewExternalAsciiStringHandle( | 5422 static i::Handle<i::String> NewExternalAsciiStringHandle( |
| 5430 i::Isolate* isolate, | 5423 i::Isolate* isolate, |
| 5431 v8::String::ExternalAsciiStringResource* resource) { | 5424 v8::String::ExternalAsciiStringResource* resource) { |
| 5432 return isolate->factory()->NewExternalStringFromAscii(resource); | 5425 return isolate->factory()->NewExternalStringFromAscii(resource); |
| 5433 } | 5426 } |
| 5434 | 5427 |
| 5435 | 5428 |
| 5436 static bool RedirectToExternalString(i::Isolate* isolate, | |
| 5437 i::Handle<i::String> parent, | |
| 5438 i::Handle<i::String> external) { | |
| 5439 if (parent->IsConsString()) { | |
| 5440 i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent); | |
| 5441 cons->set_first(*external); | |
| 5442 cons->set_second(isolate->heap()->empty_string()); | |
| 5443 } else { | |
| 5444 ASSERT(parent->IsSlicedString()); | |
| 5445 i::Handle<i::SlicedString> slice = i::Handle<i::SlicedString>::cast(parent); | |
| 5446 slice->set_parent(*external); | |
| 5447 slice->set_offset(0); | |
| 5448 } | |
| 5449 return true; | |
| 5450 } | |
| 5451 | |
| 5452 | |
| 5453 Local<String> v8::String::NewExternal( | 5429 Local<String> v8::String::NewExternal( |
| 5454 Isolate* isolate, | 5430 Isolate* isolate, |
| 5455 v8::String::ExternalStringResource* resource) { | 5431 v8::String::ExternalStringResource* resource) { |
| 5456 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 5432 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 5457 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); | 5433 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); |
| 5458 LOG_API(i_isolate, "String::NewExternal"); | 5434 LOG_API(i_isolate, "String::NewExternal"); |
| 5459 ENTER_V8(i_isolate); | 5435 ENTER_V8(i_isolate); |
| 5460 CHECK(resource && resource->data()); | 5436 CHECK(resource && resource->data()); |
| 5461 i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource); | 5437 i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource); |
| 5462 i_isolate->heap()->external_string_table()->AddString(*result); | 5438 i_isolate->heap()->external_string_table()->AddString(*result); |
| 5463 return Utils::ToLocal(result); | 5439 return Utils::ToLocal(result); |
| 5464 } | 5440 } |
| 5465 | 5441 |
| 5466 | 5442 |
| 5467 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { | 5443 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 5468 i::Handle<i::String> obj = Utils::OpenHandle(this); | 5444 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 5469 i::Isolate* isolate = obj->GetIsolate(); | 5445 i::Isolate* isolate = obj->GetIsolate(); |
| 5470 if (i::StringShape(*obj).IsExternalTwoByte()) { | 5446 if (i::StringShape(*obj).IsExternalTwoByte()) { |
| 5471 return false; // Already an external string. | 5447 return false; // Already an external string. |
| 5472 } | 5448 } |
| 5473 ENTER_V8(isolate); | 5449 ENTER_V8(isolate); |
| 5474 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { | 5450 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { |
| 5475 return false; | 5451 return false; |
| 5476 } | 5452 } |
| 5477 if (isolate->heap()->IsInGCPostProcessing()) { | 5453 if (isolate->heap()->IsInGCPostProcessing()) { |
| 5478 return false; | 5454 return false; |
| 5479 } | 5455 } |
| 5480 CHECK(resource && resource->data()); | 5456 CHECK(resource && resource->data()); |
| 5481 | 5457 |
| 5482 bool result; | 5458 bool result = obj->MakeExternal(resource); |
| 5483 i::Handle<i::String> external; | |
| 5484 if (isolate->heap()->old_pointer_space()->Contains(*obj)) { | |
| 5485 // We do not allow external strings in the old pointer space. Instead of | |
| 5486 // converting the string in-place, we keep the cons/sliced string and | |
| 5487 // point it to a newly-allocated external string. | |
| 5488 external = NewExternalStringHandle(isolate, resource); | |
| 5489 result = RedirectToExternalString(isolate, obj, external); | |
| 5490 } else { | |
| 5491 result = obj->MakeExternal(resource); | |
| 5492 external = obj; | |
| 5493 } | |
| 5494 | |
| 5495 if (result) { | 5459 if (result) { |
| 5496 ASSERT(external->IsExternalString()); | 5460 ASSERT(obj->IsExternalString()); |
| 5497 isolate->heap()->external_string_table()->AddString(*external); | 5461 isolate->heap()->external_string_table()->AddString(*obj); |
| 5498 } | 5462 } |
| 5499 return result; | 5463 return result; |
| 5500 } | 5464 } |
| 5501 | 5465 |
| 5502 | 5466 |
| 5503 Local<String> v8::String::NewExternal( | 5467 Local<String> v8::String::NewExternal( |
| 5504 Isolate* isolate, | 5468 Isolate* isolate, |
| 5505 v8::String::ExternalAsciiStringResource* resource) { | 5469 v8::String::ExternalAsciiStringResource* resource) { |
| 5506 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 5470 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 5507 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); | 5471 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5524 } | 5488 } |
| 5525 ENTER_V8(isolate); | 5489 ENTER_V8(isolate); |
| 5526 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { | 5490 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { |
| 5527 return false; | 5491 return false; |
| 5528 } | 5492 } |
| 5529 if (isolate->heap()->IsInGCPostProcessing()) { | 5493 if (isolate->heap()->IsInGCPostProcessing()) { |
| 5530 return false; | 5494 return false; |
| 5531 } | 5495 } |
| 5532 CHECK(resource && resource->data()); | 5496 CHECK(resource && resource->data()); |
| 5533 | 5497 |
| 5534 bool result; | 5498 bool result = obj->MakeExternal(resource); |
| 5535 i::Handle<i::String> external; | |
| 5536 if (isolate->heap()->old_pointer_space()->Contains(*obj)) { | |
| 5537 // We do not allow external strings in the old pointer space. Instead of | |
| 5538 // converting the string in-place, we keep the cons/sliced string and | |
| 5539 // point it to a newly-allocated external string. | |
| 5540 external = NewExternalAsciiStringHandle(isolate, resource); | |
| 5541 result = RedirectToExternalString(isolate, obj, external); | |
| 5542 } else { | |
| 5543 result = obj->MakeExternal(resource); | |
| 5544 external = obj; | |
| 5545 } | |
| 5546 | |
| 5547 if (result) { | 5499 if (result) { |
| 5548 ASSERT(external->IsExternalString()); | 5500 ASSERT(obj->IsExternalString()); |
| 5549 isolate->heap()->external_string_table()->AddString(*external); | 5501 isolate->heap()->external_string_table()->AddString(*obj); |
| 5550 } | 5502 } |
| 5551 return result; | 5503 return result; |
| 5552 } | 5504 } |
| 5553 | 5505 |
| 5554 | 5506 |
| 5555 bool v8::String::CanMakeExternal() { | 5507 bool v8::String::CanMakeExternal() { |
| 5556 if (!internal::FLAG_clever_optimizations) return false; | 5508 if (!internal::FLAG_clever_optimizations) return false; |
| 5557 i::Handle<i::String> obj = Utils::OpenHandle(this); | 5509 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 5558 i::Isolate* isolate = obj->GetIsolate(); | 5510 i::Isolate* isolate = obj->GetIsolate(); |
| 5559 | 5511 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5973 | 5925 |
| 5974 i::Handle<i::ExternalArray> elements = | 5926 i::Handle<i::ExternalArray> elements = |
| 5975 isolate->factory()->NewExternalArray( | 5927 isolate->factory()->NewExternalArray( |
| 5976 static_cast<int>(length), array_type, | 5928 static_cast<int>(length), array_type, |
| 5977 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); | 5929 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); |
| 5978 obj->set_elements(*elements); | 5930 obj->set_elements(*elements); |
| 5979 return obj; | 5931 return obj; |
| 5980 } | 5932 } |
| 5981 | 5933 |
| 5982 | 5934 |
| 5983 #define TYPED_ARRAY_NEW(TypedArray, element_type, array_type, elements_kind) \ | 5935 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \ |
| 5984 Local<TypedArray> TypedArray::New(Handle<ArrayBuffer> array_buffer, \ | 5936 Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer, \ |
| 5985 size_t byte_offset, size_t length) { \ | 5937 size_t byte_offset, size_t length) { \ |
| 5986 i::Isolate* isolate = i::Isolate::Current(); \ | 5938 i::Isolate* isolate = i::Isolate::Current(); \ |
| 5987 EnsureInitializedForIsolate(isolate, \ | 5939 EnsureInitializedForIsolate(isolate, \ |
| 5988 "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \ | 5940 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \ |
| 5989 LOG_API(isolate, \ | 5941 LOG_API(isolate, \ |
| 5990 "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \ | 5942 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \ |
| 5991 ENTER_V8(isolate); \ | 5943 ENTER_V8(isolate); \ |
| 5992 i::Handle<i::JSTypedArray> obj = \ | 5944 i::Handle<i::JSTypedArray> obj = \ |
| 5993 NewTypedArray<element_type, array_type, elements_kind>( \ | 5945 NewTypedArray<ctype, v8::kExternal##Type##Array, \ |
| 5946 i::EXTERNAL_##TYPE##_ELEMENTS>( \ |
| 5994 isolate, array_buffer, byte_offset, length); \ | 5947 isolate, array_buffer, byte_offset, length); \ |
| 5995 return Utils::ToLocal##TypedArray(obj); \ | 5948 return Utils::ToLocal##Type##Array(obj); \ |
| 5996 } | 5949 } |
| 5997 | 5950 |
| 5998 | 5951 |
| 5999 TYPED_ARRAY_NEW(Uint8Array, uint8_t, kExternalUnsignedByteArray, | 5952 TYPED_ARRAYS(TYPED_ARRAY_NEW) |
| 6000 i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS) | |
| 6001 TYPED_ARRAY_NEW(Uint8ClampedArray, uint8_t, kExternalPixelArray, | |
| 6002 i::EXTERNAL_PIXEL_ELEMENTS) | |
| 6003 TYPED_ARRAY_NEW(Int8Array, int8_t, kExternalByteArray, | |
| 6004 i::EXTERNAL_BYTE_ELEMENTS) | |
| 6005 TYPED_ARRAY_NEW(Uint16Array, uint16_t, kExternalUnsignedShortArray, | |
| 6006 i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS) | |
| 6007 TYPED_ARRAY_NEW(Int16Array, int16_t, kExternalShortArray, | |
| 6008 i::EXTERNAL_SHORT_ELEMENTS) | |
| 6009 TYPED_ARRAY_NEW(Uint32Array, uint32_t, kExternalUnsignedIntArray, | |
| 6010 i::EXTERNAL_UNSIGNED_INT_ELEMENTS) | |
| 6011 TYPED_ARRAY_NEW(Int32Array, int32_t, kExternalIntArray, | |
| 6012 i::EXTERNAL_INT_ELEMENTS) | |
| 6013 TYPED_ARRAY_NEW(Float32Array, float, kExternalFloatArray, | |
| 6014 i::EXTERNAL_FLOAT_ELEMENTS) | |
| 6015 TYPED_ARRAY_NEW(Float64Array, double, kExternalDoubleArray, | |
| 6016 i::EXTERNAL_DOUBLE_ELEMENTS) | |
| 6017 | |
| 6018 #undef TYPED_ARRAY_NEW | 5953 #undef TYPED_ARRAY_NEW |
| 6019 | 5954 |
| 6020 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer, | 5955 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer, |
| 6021 size_t byte_offset, size_t byte_length) { | 5956 size_t byte_offset, size_t byte_length) { |
| 6022 i::Isolate* isolate = i::Isolate::Current(); | 5957 i::Isolate* isolate = i::Isolate::Current(); |
| 6023 EnsureInitializedForIsolate( | 5958 EnsureInitializedForIsolate( |
| 6024 isolate, "v8::DataView::New(void*, size_t, size_t)"); | 5959 isolate, "v8::DataView::New(void*, size_t, size_t)"); |
| 6025 LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)"); | 5960 LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)"); |
| 6026 ENTER_V8(isolate); | 5961 ENTER_V8(isolate); |
| 6027 i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView(); | 5962 i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView(); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6351 callback); | 6286 callback); |
| 6352 } | 6287 } |
| 6353 | 6288 |
| 6354 | 6289 |
| 6355 void V8::AddCallCompletedCallback(CallCompletedCallback callback) { | 6290 void V8::AddCallCompletedCallback(CallCompletedCallback callback) { |
| 6356 if (callback == NULL) return; | 6291 if (callback == NULL) return; |
| 6357 i::V8::AddCallCompletedCallback(callback); | 6292 i::V8::AddCallCompletedCallback(callback); |
| 6358 } | 6293 } |
| 6359 | 6294 |
| 6360 | 6295 |
| 6296 void V8::RunMicrotasks(Isolate* isolate) { |
| 6297 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 6298 i::HandleScope scope(i_isolate); |
| 6299 i::V8::RunMicrotasks(i_isolate); |
| 6300 } |
| 6301 |
| 6302 |
| 6303 void V8::EnqueueMicrotask(Isolate* isolate, Handle<Function> microtask) { |
| 6304 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 6305 ENTER_V8(i_isolate); |
| 6306 i::Execution::EnqueueMicrotask(i_isolate, Utils::OpenHandle(*microtask)); |
| 6307 } |
| 6308 |
| 6309 |
| 6310 void V8::SetAutorunMicrotasks(Isolate* isolate, bool autorun) { |
| 6311 reinterpret_cast<i::Isolate*>(isolate)->set_autorun_microtasks(autorun); |
| 6312 } |
| 6313 |
| 6314 |
| 6361 void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) { | 6315 void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) { |
| 6362 i::V8::RemoveCallCompletedCallback(callback); | 6316 i::V8::RemoveCallCompletedCallback(callback); |
| 6363 } | 6317 } |
| 6364 | 6318 |
| 6365 | 6319 |
| 6366 void V8::TerminateExecution(Isolate* isolate) { | 6320 void V8::TerminateExecution(Isolate* isolate) { |
| 6367 // If no isolate is supplied, use the default isolate. | 6321 // If no isolate is supplied, use the default isolate. |
| 6368 if (isolate != NULL) { | 6322 if (isolate != NULL) { |
| 6369 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution(); | 6323 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution(); |
| 6370 } else { | 6324 } else { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6399 | 6353 |
| 6400 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) { | 6354 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) { |
| 6401 CHECK(i::FLAG_expose_gc); | 6355 CHECK(i::FLAG_expose_gc); |
| 6402 if (type == kMinorGarbageCollection) { | 6356 if (type == kMinorGarbageCollection) { |
| 6403 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage( | 6357 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage( |
| 6404 i::NEW_SPACE, "Isolate::RequestGarbageCollection", | 6358 i::NEW_SPACE, "Isolate::RequestGarbageCollection", |
| 6405 kGCCallbackFlagForced); | 6359 kGCCallbackFlagForced); |
| 6406 } else { | 6360 } else { |
| 6407 ASSERT_EQ(kFullGarbageCollection, type); | 6361 ASSERT_EQ(kFullGarbageCollection, type); |
| 6408 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage( | 6362 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage( |
| 6409 i::Heap::kNoGCFlags, "Isolate::RequestGarbageCollection", | 6363 i::Heap::kAbortIncrementalMarkingMask, |
| 6410 kGCCallbackFlagForced); | 6364 "Isolate::RequestGarbageCollection", kGCCallbackFlagForced); |
| 6411 } | 6365 } |
| 6412 } | 6366 } |
| 6413 | 6367 |
| 6414 | 6368 |
| 6415 Isolate* Isolate::GetCurrent() { | 6369 Isolate* Isolate::GetCurrent() { |
| 6416 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); | 6370 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); |
| 6417 return reinterpret_cast<Isolate*>(isolate); | 6371 return reinterpret_cast<Isolate*>(isolate); |
| 6418 } | 6372 } |
| 6419 | 6373 |
| 6420 | 6374 |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6961 | 6915 |
| 6962 | 6916 |
| 6963 Handle<Value> HeapGraphEdge::GetName() const { | 6917 Handle<Value> HeapGraphEdge::GetName() const { |
| 6964 i::Isolate* isolate = i::Isolate::Current(); | 6918 i::Isolate* isolate = i::Isolate::Current(); |
| 6965 i::HeapGraphEdge* edge = ToInternal(this); | 6919 i::HeapGraphEdge* edge = ToInternal(this); |
| 6966 switch (edge->type()) { | 6920 switch (edge->type()) { |
| 6967 case i::HeapGraphEdge::kContextVariable: | 6921 case i::HeapGraphEdge::kContextVariable: |
| 6968 case i::HeapGraphEdge::kInternal: | 6922 case i::HeapGraphEdge::kInternal: |
| 6969 case i::HeapGraphEdge::kProperty: | 6923 case i::HeapGraphEdge::kProperty: |
| 6970 case i::HeapGraphEdge::kShortcut: | 6924 case i::HeapGraphEdge::kShortcut: |
| 6925 case i::HeapGraphEdge::kWeak: |
| 6971 return ToApiHandle<String>( | 6926 return ToApiHandle<String>( |
| 6972 isolate->factory()->InternalizeUtf8String(edge->name())); | 6927 isolate->factory()->InternalizeUtf8String(edge->name())); |
| 6973 case i::HeapGraphEdge::kElement: | 6928 case i::HeapGraphEdge::kElement: |
| 6974 case i::HeapGraphEdge::kHidden: | 6929 case i::HeapGraphEdge::kHidden: |
| 6975 case i::HeapGraphEdge::kWeak: | |
| 6976 return ToApiHandle<Number>( | 6930 return ToApiHandle<Number>( |
| 6977 isolate->factory()->NewNumberFromInt(edge->index())); | 6931 isolate->factory()->NewNumberFromInt(edge->index())); |
| 6978 default: UNREACHABLE(); | 6932 default: UNREACHABLE(); |
| 6979 } | 6933 } |
| 6980 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); | 6934 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); |
| 6981 } | 6935 } |
| 6982 | 6936 |
| 6983 | 6937 |
| 6984 const HeapGraphNode* HeapGraphEdge::GetFromNode() const { | 6938 const HeapGraphNode* HeapGraphEdge::GetFromNode() const { |
| 6985 const i::HeapEntry* from = ToInternal(this)->from(); | 6939 const i::HeapEntry* from = ToInternal(this)->from(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 7010 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name())); | 6964 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name())); |
| 7011 } | 6965 } |
| 7012 | 6966 |
| 7013 | 6967 |
| 7014 SnapshotObjectId HeapGraphNode::GetId() const { | 6968 SnapshotObjectId HeapGraphNode::GetId() const { |
| 7015 return ToInternal(this)->id(); | 6969 return ToInternal(this)->id(); |
| 7016 } | 6970 } |
| 7017 | 6971 |
| 7018 | 6972 |
| 7019 int HeapGraphNode::GetSelfSize() const { | 6973 int HeapGraphNode::GetSelfSize() const { |
| 6974 size_t size = ToInternal(this)->self_size(); |
| 6975 CHECK(size <= static_cast<size_t>(internal::kMaxInt)); |
| 6976 return static_cast<int>(size); |
| 6977 } |
| 6978 |
| 6979 |
| 6980 size_t HeapGraphNode::GetShallowSize() const { |
| 7020 return ToInternal(this)->self_size(); | 6981 return ToInternal(this)->self_size(); |
| 7021 } | 6982 } |
| 7022 | 6983 |
| 7023 | 6984 |
| 7024 int HeapGraphNode::GetChildrenCount() const { | 6985 int HeapGraphNode::GetChildrenCount() const { |
| 7025 return ToInternal(this)->children().length(); | 6986 return ToInternal(this)->children().length(); |
| 7026 } | 6987 } |
| 7027 | 6988 |
| 7028 | 6989 |
| 7029 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { | 6990 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7416 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate()); | 7377 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate()); |
| 7417 Address callback_address = | 7378 Address callback_address = |
| 7418 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); | 7379 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); |
| 7419 VMState<EXTERNAL> state(isolate); | 7380 VMState<EXTERNAL> state(isolate); |
| 7420 ExternalCallbackScope call_scope(isolate, callback_address); | 7381 ExternalCallbackScope call_scope(isolate, callback_address); |
| 7421 callback(info); | 7382 callback(info); |
| 7422 } | 7383 } |
| 7423 | 7384 |
| 7424 | 7385 |
| 7425 } } // namespace v8::internal | 7386 } } // namespace v8::internal |
| OLD | NEW |