Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 61211ec6cbc53e3562cbb862c00432ac6d5e7667..f24b895c0d5503e0b844a6439de646bca033f2af 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,39 @@ const HOptimizedGraphBuilder::InlineFunctionGenerator |
#undef INLINE_FUNCTION_GENERATOR_ADDRESS |
+template <class ViewClass> |
+void HGraphBuilder::BuildArrayBufferViewInitialization( |
+ HValue* obj, |
+ HValue* buffer, |
+ HValue* byte_offset, |
+ HValue* byte_length) { |
+ |
+ for (int offset = ViewClass::kSize; |
+ offset < ViewClass::kSizeWithInternalFields; |
+ offset += kPointerSize) { |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(offset), |
+ Add<HConstant>(static_cast<int32_t>(0))); |
+ } |
+ |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(ViewClass::kBufferOffset), buffer); |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(ViewClass::kByteOffsetOffset), |
+ byte_offset); |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(ViewClass::kByteLengthOffset), |
+ byte_length); |
+ |
+ HObjectAccess weak_first_view_access = |
+ HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset); |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(ViewClass::kWeakNextOffset), |
+ Add<HLoadNamedField>(buffer, weak_first_view_access)); |
+ Add<HStoreNamedField>(buffer, weak_first_view_access, obj); |
+} |
+ |
+ |
void HOptimizedGraphBuilder::VisitDataViewInitialize( |
CallRuntime* expr) { |
ZoneList<Expression*>* arguments = expr->arguments(); |
@@ -8072,31 +8106,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>( |
+ 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(); |
+ 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, |
- HObjectAccess::ForJSObjectOffset( |
- JSArrayBuffer::kWeakFirstViewOffset))); |
- Add<HStoreNamedField>(buffer, |
- HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset), |
- obj); |
+ 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>( |
+ 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 = AddUncasted<HDiv>(byte_length, |
+ Add<HConstant>(static_cast<int32_t>(element_size))); |
+ |
+ Add<HStoreNamedField>(obj, |
+ HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset), |
danno
2013/11/21 20:44:35
Here an elsewhere, does it perhaps make sense to w
Dmitry Lomov (no reviews)
2013/11/22 12:40:27
Done, albeit reluctantly. I see the value of encap
|
+ length); |
+ |
+ HValue* elements = |
+ Add<HAllocate>( |
danno
2013/11/21 20:44:35
nit: 4 char indent
Dmitry Lomov (no reviews)
2013/11/22 12:40:27
Done.
|
+ 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)); |
+ |
danno
2013/11/21 20:44:35
nit: Group the load/store pairs and their preparat
Dmitry Lomov (no reviews)
2013/11/22 12:40:27
Done.
|
+ Add<HStoreNamedField>(elements, |
+ HObjectAccess::ForMap(), |
+ Add<HConstant>(external_array_map)); |
danno
2013/11/21 20:44:35
nit: And insert one after this line
Dmitry Lomov (no reviews)
2013/11/22 12:40:27
Done.
|
+ HObjectAccess backing_store_access = |
+ HObjectAccess::ForJSObjectOffset( |
+ JSArrayBuffer::kBackingStoreOffset, Representation::External()); |
+ |
danno
2013/11/21 20:44:35
nit: remove this line
Dmitry Lomov (no reviews)
2013/11/22 12:40:27
Done.
|
+ HValue* backing_store = Add<HLoadNamedField>(buffer, backing_store_access); |
+ |
+ 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; |
+ } |
+ |
+ Add<HStoreNamedField>(elements, |
+ HObjectAccess::ForJSObjectOffset( |
+ ExternalArray::kExternalPointerOffset, Representation::External()), |
+ typed_array_start); |
+ Add<HStoreNamedField>(elements, |
+ HObjectAccess::ForJSObjectOffset(ExternalArray::kLengthOffset), |
danno
2013/11/21 20:44:35
I think it's safe to use HObjectAccoess::ForFixedA
|
+ 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(); |
} |
@@ -8115,6 +8249,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) == '_'); |