| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 6bc7f6982fb798f442eb5a55da8b380ac7868d0c..76a91aac0c87267e7c7c90aa85c3c239878be189 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -6475,7 +6475,8 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val));
|
| } else {
|
| ASSERT(IsFastElementsKind(elements_kind) ||
|
| - IsExternalArrayElementsKind(elements_kind));
|
| + IsExternalArrayElementsKind(elements_kind) ||
|
| + IsFixedTypedArrayElementsKind(elements_kind));
|
| LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
|
| // Happily, mapcompare is a checked object.
|
| access = BuildUncheckedMonomorphicElementAccess(
|
| @@ -8421,9 +8422,6 @@ void HGraphBuilder::BuildArrayBufferViewInitialization(
|
|
|
| Add<HStoreNamedField>(
|
| obj,
|
| - HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
|
| - Add<HStoreNamedField>(
|
| - obj,
|
| HObjectAccess::ForJSArrayBufferViewByteOffset(),
|
| byte_offset);
|
| Add<HStoreNamedField>(
|
| @@ -8431,14 +8429,27 @@ void HGraphBuilder::BuildArrayBufferViewInitialization(
|
| HObjectAccess::ForJSArrayBufferViewByteLength(),
|
| byte_length);
|
|
|
| - HObjectAccess weak_first_view_access =
|
| - HObjectAccess::ForJSArrayBufferWeakFirstView();
|
| - Add<HStoreNamedField>(obj,
|
| - HObjectAccess::ForJSArrayBufferViewWeakNext(),
|
| - Add<HLoadNamedField>(buffer, static_cast<HValue*>(NULL),
|
| - weak_first_view_access));
|
| - Add<HStoreNamedField>(
|
| - buffer, weak_first_view_access, obj);
|
| + if (buffer != NULL) {
|
| + Add<HStoreNamedField>(
|
| + obj,
|
| + HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
|
| + HObjectAccess weak_first_view_access =
|
| + HObjectAccess::ForJSArrayBufferWeakFirstView();
|
| + Add<HStoreNamedField>(obj,
|
| + HObjectAccess::ForJSArrayBufferViewWeakNext(),
|
| + Add<HLoadNamedField>(buffer,
|
| + static_cast<HValue*>(NULL),
|
| + weak_first_view_access));
|
| + Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
|
| + } else {
|
| + Add<HStoreNamedField>(
|
| + obj,
|
| + HObjectAccess::ForJSArrayBufferViewBuffer(),
|
| + Add<HConstant>(static_cast<int32_t>(0)));
|
| + Add<HStoreNamedField>(obj,
|
| + HObjectAccess::ForJSArrayBufferViewWeakNext(),
|
| + graph()->GetConstantUndefined());
|
| + }
|
| }
|
|
|
|
|
| @@ -8464,9 +8475,26 @@ void HOptimizedGraphBuilder::VisitDataViewInitialize(
|
| obj, buffer, byte_offset, byte_length);
|
| }
|
|
|
| +static Handle<Map> TypedArrayMap(Isolate* isolate,
|
| + ExternalArrayType array_type,
|
| + ElementsKind target_kind) {
|
| + Handle<Context> native_context = isolate->native_context();
|
| + Handle<JSFunction> fun;
|
| + switch (array_type) {
|
| +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| + case kExternal##Type##Array: \
|
| + fun = Handle<JSFunction>(native_context->type##_array_fun()); \
|
| + break;
|
| +
|
| + TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| +#undef TYPED_ARRAY_CASE
|
| + }
|
| + Handle<Map> map(fun->initial_map());
|
| + return Map::AsElementsKind(map, target_kind);
|
| +}
|
| +
|
|
|
| -void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
| - CallRuntime* expr) {
|
| +void HOptimizedGraphBuilder::VisitTypedArrayInitialize(CallRuntime* expr) {
|
| ZoneList<Expression*>* arguments = expr->arguments();
|
|
|
| NoObservableSideEffectsScope scope(this);
|
| @@ -8488,8 +8516,13 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
| ASSERT(value->IsSmi());
|
| int array_id = Smi::cast(*value)->value();
|
|
|
| - CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
|
| - HValue* buffer = Pop();
|
| + HValue* buffer;
|
| + if (!arguments->at(kBufferArg)->IsNullLiteral()) {
|
| + CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
|
| + buffer = Pop();
|
| + } else {
|
| + buffer = NULL;
|
| + }
|
|
|
| HValue* byte_offset;
|
| bool is_zero_byte_offset;
|
| @@ -8503,6 +8536,7 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
| CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
|
| byte_offset = Pop();
|
| is_zero_byte_offset = false;
|
| + ASSERT(buffer != NULL);
|
| }
|
|
|
| CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
|
| @@ -8515,13 +8549,24 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
| byte_offset_smi.Then();
|
| }
|
|
|
| + ExternalArrayType array_type =
|
| + kExternalInt8Array; // Bogus initialization.
|
| + size_t element_size = 1; // Bogus initialization.
|
| + ElementsKind external_elements_kind = // Bogus initialization.
|
| + EXTERNAL_INT8_ELEMENTS;
|
| + ElementsKind fixed_elements_kind = // Bogus initialization.
|
| + INT8_ELEMENTS;
|
| + Runtime::ArrayIdToTypeAndSize(array_id,
|
| + &array_type,
|
| + &external_elements_kind,
|
| + &fixed_elements_kind,
|
| + &element_size);
|
| +
|
| +
|
| { // byte_offset is Smi.
|
| BuildArrayBufferViewInitialization<JSTypedArray>(
|
| obj, buffer, byte_offset, byte_length);
|
|
|
| - ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
|
| - size_t element_size = 1; // Bogus initialization.
|
| - Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size);
|
|
|
| HInstruction* length = AddUncasted<HDiv>(byte_length,
|
| Add<HConstant>(static_cast<int32_t>(element_size)));
|
| @@ -8530,40 +8575,94 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
| HObjectAccess::ForJSTypedArrayLength(),
|
| length);
|
|
|
| - Handle<Map> external_array_map(
|
| - isolate()->heap()->MapForExternalArrayType(array_type));
|
| -
|
| - HValue* elements =
|
| - Add<HAllocate>(
|
| - Add<HConstant>(ExternalArray::kAlignedSize),
|
| - HType::JSArray(),
|
| - NOT_TENURED,
|
| - external_array_map->instance_type());
|
| + HValue* elements;
|
| + if (buffer != NULL) {
|
| + Handle<Map> external_array_map(
|
| + isolate()->heap()->MapForExternalArrayType(array_type));
|
| + elements =
|
| + Add<HAllocate>(
|
| + Add<HConstant>(ExternalArray::kAlignedSize),
|
| + HType::JSArray(),
|
| + NOT_TENURED,
|
| + external_array_map->instance_type());
|
| +
|
| + AddStoreMapConstant(elements, external_array_map);
|
| +
|
| + HValue* backing_store = Add<HLoadNamedField>(
|
| + buffer, static_cast<HValue*>(NULL),
|
| + HObjectAccess::ForJSArrayBufferBackingStore());
|
| +
|
| + HValue* typed_array_start;
|
| + if (is_zero_byte_offset) {
|
| + typed_array_start = backing_store;
|
| + } else {
|
| + HInstruction* external_pointer =
|
| + AddUncasted<HAdd>(backing_store, byte_offset);
|
| + // Arguments are checked prior to call to TypedArrayInitialize,
|
| + // including byte_offset.
|
| + external_pointer->ClearFlag(HValue::kCanOverflow);
|
| + typed_array_start = external_pointer;
|
| + }
|
|
|
| - AddStoreMapConstant(elements, external_array_map);
|
|
|
| - HValue* backing_store = Add<HLoadNamedField>(
|
| - buffer, static_cast<HValue*>(NULL),
|
| - HObjectAccess::ForJSArrayBufferBackingStore());
|
| + Add<HStoreNamedField>(elements,
|
| + HObjectAccess::ForExternalArrayExternalPointer(),
|
| + typed_array_start);
|
|
|
| - HValue* typed_array_start;
|
| - if (is_zero_byte_offset) {
|
| - typed_array_start = backing_store;
|
| + Handle<Map> obj_map = TypedArrayMap(
|
| + isolate(), array_type, external_elements_kind);
|
| + AddStoreMapConstant(obj, obj_map);
|
| + Add<HStoreNamedField>(elements,
|
| + HObjectAccess::ForFixedArrayLength(),
|
| + length, INITIALIZING_STORE);
|
| } else {
|
| - HInstruction* external_pointer =
|
| - AddUncasted<HAdd>(backing_store, byte_offset);
|
| - // Arguments are checked prior to call to TypedArrayInitialize,
|
| - // including byte_offset.
|
| - external_pointer->ClearFlag(HValue::kCanOverflow);
|
| - typed_array_start = external_pointer;
|
| - }
|
| -
|
| - Add<HStoreNamedField>(elements,
|
| - HObjectAccess::ForExternalArrayExternalPointer(),
|
| - typed_array_start);
|
| - Add<HStoreNamedField>(elements,
|
| - HObjectAccess::ForFixedArrayLength(),
|
| - length);
|
| + ASSERT(is_zero_byte_offset);
|
| +
|
| + STATIC_ASSERT(
|
| + (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
|
| + HValue* total_size;
|
| +
|
| + if (element_size % kObjectAlignment != 0) {
|
| + HConstant* header_size = Add<HConstant>(static_cast<int32_t>(
|
| + FixedTypedArrayBase::kHeaderSize + kObjectAlignmentMask));
|
| + HValue* unaligned_size = AddUncasted<HAdd>(byte_length, header_size);
|
| + unaligned_size->ClearFlag(HValue::kCanOverflow);
|
| + total_size = AddUncasted<HBitwise>(
|
| + Token::BIT_AND, unaligned_size,
|
| + Add<HConstant>(static_cast<int32_t>(~kObjectAlignmentMask)));
|
| + } else {
|
| + total_size = AddUncasted<HAdd>(byte_length,
|
| + Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
|
| + total_size->ClearFlag(HValue::kCanOverflow);
|
| + }
|
| +
|
| + Handle<Map> fixed_typed_array_map(
|
| + isolate()->heap()->MapForFixedTypedArray(array_type));
|
| + elements =
|
| + Add<HAllocate>(total_size, HType::JSArray(),
|
| + NOT_TENURED,
|
| + fixed_typed_array_map->instance_type());
|
| + AddStoreMapConstant(elements, fixed_typed_array_map);
|
| +
|
| + Add<HStoreNamedField>(elements,
|
| + HObjectAccess::ForFixedArrayLength(),
|
| + length, INITIALIZING_STORE);
|
| + HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
|
| +
|
| + {
|
| + LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
|
| +
|
| + HValue* key = builder.BeginBody(
|
| + Add<HConstant>(static_cast<int32_t>(0)),
|
| + length, Token::LT);
|
| + Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
|
| +
|
| + builder.EndBody();
|
| + }
|
| + }
|
| + Add<HStoreNamedField>(
|
| + elements, HObjectAccess::ForFixedArrayLength(), length,
|
| + INITIALIZING_STORE);
|
| Add<HStoreNamedField>(
|
| obj, HObjectAccess::ForElementsPointer(), elements);
|
| }
|
| @@ -8609,6 +8708,14 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
|
| return ast_context()->ReturnInstruction(max_smi, expr->id());
|
| }
|
|
|
| +
|
| + if (function->function_id == Runtime::kTypedArrayInHeapThreshold) {
|
| + ASSERT(expr->arguments()->length() == 0);
|
| + HConstant* value = New<HConstant>(
|
| + static_cast<int32_t>(FLAG_typed_array_in_heap_threshold));
|
| + return ast_context()->ReturnInstruction(value, expr->id());
|
| + }
|
| +
|
| if (function->intrinsic_type == Runtime::INLINE) {
|
| ASSERT(expr->name()->length() > 0);
|
| ASSERT(expr->name()->Get(0) == '_');
|
|
|