Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 61211ec6cbc53e3562cbb862c00432ac6d5e7667..356f90a1c911ad75976907469531c7dc530537bf 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -58,6 +58,7 @@ |
| #include "hydrogen-uint32-analysis.h" |
| #include "lithium-allocator.h" |
| #include "parser.h" |
| +#include "runtime.h" |
| #include "scopeinfo.h" |
| #include "scopes.h" |
| #include "stub-cache.h" |
| @@ -8054,6 +8055,42 @@ const HOptimizedGraphBuilder::InlineFunctionGenerator |
| #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| +template <class ViewClass> |
| +void BuildArrayBufferViewInitialization( |
| + HGraphBuilder* graph, |
|
danno
2013/11/20 13:50:50
this should be called "builder". Consider moving t
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + HValue* obj, |
| + HValue* buffer, |
| + HValue* byte_offset, |
| + HValue* byte_length) { |
| + |
| + for (int offset = ViewClass::kSize; |
| + offset < ViewClass::kSizeWithInternalFields; |
|
danno
2013/11/20 13:50:50
nit: alignment
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + offset += kPointerSize) { |
| + graph->Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(offset), |
| + graph->Add<HConstant>(static_cast<int32_t>(0))); |
| + } |
| + |
| + graph->Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(ViewClass::kBufferOffset), buffer); |
| + graph->Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(ViewClass::kByteOffsetOffset), |
| + byte_offset); |
| + graph->Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(ViewClass::kByteLengthOffset), |
| + byte_length); |
| + |
| + graph->Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(ViewClass::kWeakNextOffset), |
| + graph->Add<HLoadNamedField>(buffer, |
| + HObjectAccess::ForJSObjectOffset( |
| + JSArrayBuffer::kWeakFirstViewOffset))); |
|
danno
2013/11/20 13:50:50
nit: 4 char indent. Perhaps move the object access
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + graph->Add<HStoreNamedField>(buffer, |
| + HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset), |
| + obj); |
| +} |
| + |
| + |
| void HOptimizedGraphBuilder::VisitDataViewInitialize( |
| CallRuntime* expr) { |
| ZoneList<Expression*>* arguments = expr->arguments(); |
| @@ -8072,31 +8109,131 @@ void HOptimizedGraphBuilder::VisitDataViewInitialize( |
| CHECK_ALIVE(VisitForValue(arguments->at(3))); |
| HValue* byte_length = Pop(); |
| - for (int offset = JSDataView::kSize; |
| - offset < JSDataView::kSizeWithInternalFields; |
| - offset += kPointerSize) { |
| - Add<HStoreNamedField>(obj, |
| - HObjectAccess::ForJSObjectOffset(offset), |
| - Add<HConstant>(static_cast<int32_t>(0))); |
| + BuildArrayBufferViewInitialization<JSDataView>( |
| + this, obj, buffer, byte_offset, byte_length); |
| +} |
| + |
| + |
| +void HOptimizedGraphBuilder::VisitTypedArrayInitialize( |
| + CallRuntime* expr) { |
| + ZoneList<Expression*>* arguments = expr->arguments(); |
| + |
| + NoObservableSideEffectsScope scope(this); |
| + static const int kObjectArg = 0; |
| + static const int kArrayIdArg = 1; |
| + static const int kBufferArg = 2; |
| + static const int kByteOffsetArg = 3; |
| + static const int kByteLengthArg = 4; |
| + static const int kArgsLength = 5; |
| + ASSERT(arguments->length() == kArgsLength); |
| + |
| + |
| + CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg))); |
| + HValue* obj = Pop(); |
| + |
| + ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral); |
| + Handle<Object> value = |
| + static_cast<Literal*>(arguments->at(kArrayIdArg))->value(); |
|
danno
2013/11/20 13:50:50
4-char indent
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + ASSERT(value->IsSmi()); |
| + int array_id = Smi::cast(*value)->value(); |
| + |
| + CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg))); |
| + HValue* buffer = Pop(); |
| + |
| + HValue* byte_offset; |
| + bool is_zero_byte_offset; |
| + |
| + if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral |
| + && Smi::FromInt(0) == |
| + *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) { |
| + byte_offset = Add<HConstant>(static_cast<int32_t>(0)); |
| + is_zero_byte_offset = true; |
| + } else { |
| + CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg))); |
| + byte_offset = Pop(); |
| + is_zero_byte_offset = false; |
| } |
| - Add<HStoreNamedField>(obj, |
| - HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer); |
| - Add<HStoreNamedField>(obj, |
| - HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset), |
| - byte_offset); |
| - Add<HStoreNamedField>(obj, |
| - HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset), |
| - byte_length); |
| + CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg))); |
| + HValue* byte_length = Pop(); |
| - Add<HStoreNamedField>(obj, |
| - HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset), |
| - Add<HLoadNamedField>(buffer, |
| + IfBuilder byte_offset_smi(this); |
| + |
| + if (!is_zero_byte_offset) { |
| + byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); |
| + byte_offset_smi.Then(); |
| + } |
| + |
| + { // byte_offset is Smi. |
| + BuildArrayBufferViewInitialization<JSTypedArray>( |
| + this, obj, buffer, byte_offset, byte_length); |
| + |
| + ExternalArrayType array_type = kExternalByteArray; // Bogus initialization. |
| + size_t element_size = 1; // Bogus initialization. |
| + Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); |
| + |
| + HInstruction* length = Add<HDiv>(byte_length, |
| + Add<HConstant>(static_cast<int32_t>(element_size))); |
| + |
| + Add<HStoreNamedField>(obj, |
| + HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset), |
| + length); |
| + |
| + HValue* elements = |
| + Add<HAllocate>( |
| + Add<HConstant>(ExternalArray::kAlignedSize), |
| + HType::JSArray(), |
| + NOT_TENURED, |
| + static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type)); |
| + |
| + Handle<Map> external_array_map( |
| + isolate()->heap()->MapForExternalArrayType(array_type)); |
| + |
| + Add<HStoreNamedField>(elements, |
| + HObjectAccess::ForMap(), |
| + Add<HConstant>(external_array_map)); |
| + HValue* backing_store = |
| + Add<HLoadNamedField>(buffer, |
| HObjectAccess::ForJSObjectOffset( |
|
danno
2013/11/20 13:50:50
nit: 4 char indent
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| - JSArrayBuffer::kWeakFirstViewOffset))); |
| - Add<HStoreNamedField>(buffer, |
| - HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset), |
| - obj); |
| + JSArrayBuffer::kBackingStoreOffset, Representation::External())); |
|
danno
2013/11/20 13:50:50
Same here. Maybe move the access into a local vari
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + |
| + HValue* typed_array_start; |
| + if (is_zero_byte_offset) { |
| + typed_array_start = backing_store; |
| + } else { |
| + HInstruction* external_pointer = |
| + HAdd::New( |
| + zone(), graph()->GetInvalidContext(), backing_store, byte_offset); |
|
danno
2013/11/20 13:50:50
You should be able to use Add<> now, shouldn't you
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + // Arguments are checked prior to call to TypedArrayInitialize, |
| + // including byte_offset. |
| + external_pointer->ClearFlag(HValue::kCanOverflow); |
| + typed_array_start = AddInstruction(external_pointer); |
| + } |
| + |
| + Add<HStoreNamedField>(elements, |
| + HObjectAccess::ForJSObjectOffset( |
| + ExternalArray::kExternalPointerOffset, Representation::External()), |
|
danno
2013/11/20 13:50:50
nit: 4 char indent?
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + typed_array_start); |
| + Add<HStoreNamedField>(elements, |
| + HObjectAccess::ForJSObjectOffset(ExternalArray::kLengthOffset), |
| + length); |
| + Add<HStoreNamedField>( |
| + obj, HObjectAccess::ForElementsPointer(), elements); |
| + } |
| + |
| + if (!is_zero_byte_offset) { |
| + byte_offset_smi.Else(); |
| + { // byte_offset is not Smi. |
| + Push(Add<HPushArgument>(obj)); |
| + VisitArgument(arguments->at(kArrayIdArg)); |
| + Push(Add<HPushArgument>(buffer)); |
| + Push(Add<HPushArgument>(byte_offset)); |
| + Push(Add<HPushArgument>(byte_length)); |
| + Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); |
| + Drop(kArgsLength); |
| + } |
| + byte_offset_smi.End(); |
|
danno
2013/11/20 13:50:50
Shouldn't this be after the } below? It should alw
Dmitry Lomov (no reviews)
2013/11/20 17:38:56
Done.
|
| + } |
| } |
| @@ -8115,6 +8252,16 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| return VisitDataViewInitialize(expr); |
| } |
| + if (function->function_id == Runtime::kTypedArrayInitialize) { |
| + return VisitTypedArrayInitialize(expr); |
| + } |
| + |
| + if (function->function_id == Runtime::kMaxSmi) { |
| + ASSERT(expr->arguments()->length() == 0); |
| + HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue)); |
| + return ast_context()->ReturnInstruction(max_smi, expr->id()); |
| + } |
| + |
| if (function->intrinsic_type == Runtime::INLINE) { |
| ASSERT(expr->name()->length() > 0); |
| ASSERT(expr->name()->Get(0) == '_'); |