From: bmeurer@chromium.org Date: Wed, 10 Sep 2014 12:29:48 +0000 (+0000) Subject: [turbofan] Lower JSStoreProperty during JS typed lowering. X-Git-Tag: upstream/4.7.83~7012 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cf293f77802c2f7fecfdea237a83147131c484e3;p=platform%2Fupstream%2Fv8.git [turbofan] Lower JSStoreProperty during JS typed lowering. Note that we cannot yet emit a diamond here (patch is ready), because the scheduler is still broken wrt. free floating control (seems related although this diamond is not free floating). TEST=cctest R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/557123005 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23838 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index a8b4823..c4e7b2b 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -28,9 +28,12 @@ static void RelaxEffects(Node* node) { } +JSTypedLowering::~JSTypedLowering() {} + + Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { NodeProperties::ReplaceWithValue(old, node, node); - return Reducer::Changed(node); + return Changed(node); } @@ -500,7 +503,7 @@ Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { } -Reduction JSTypedLowering::ReduceJSPropertyLoad(Node* node) { +Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { Node* key = NodeProperties::GetValueInput(node, 1); Node* base = NodeProperties::GetValueInput(node, 0); Type* key_type = NodeProperties::GetBounds(key).upper; @@ -537,6 +540,45 @@ Reduction JSTypedLowering::ReduceJSPropertyLoad(Node* node) { } +Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { + Node* key = NodeProperties::GetValueInput(node, 1); + Node* base = NodeProperties::GetValueInput(node, 0); + Node* value = NodeProperties::GetValueInput(node, 2); + Type* key_type = NodeProperties::GetBounds(key).upper; + Type* base_type = NodeProperties::GetBounds(base).upper; + // TODO(mstarzinger): This lowering is not correct if: + // a) The typed array turns external (i.e. MaterializeArrayBuffer) + // b) The typed array or it's buffer is neutered. + // c) The index is out of bounds + if (key_type->Is(Type::Integral32()) && base_type->IsConstant() && + base_type->AsConstant()->Value()->IsJSTypedArray()) { + // JSStoreProperty(typed-array, int32, value) + JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value()); + ElementsKind elements_kind = array->map()->elements_kind(); + ExternalArrayType type = array->type(); + ElementAccess element_access; + Node* elements = graph()->NewNode( + simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base, + NodeProperties::GetEffectInput(node)); + if (IsExternalArrayElementsKind(elements_kind)) { + elements = graph()->NewNode( + simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()), + elements, NodeProperties::GetEffectInput(node)); + element_access = AccessBuilder::ForTypedArrayElement(type, true); + } else { + DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); + element_access = AccessBuilder::ForTypedArrayElement(type, false); + } + Node* store = + graph()->NewNode(simplified()->StoreElement(element_access), elements, + key, value, NodeProperties::GetEffectInput(node), + NodeProperties::GetControlInput(node)); + return ReplaceEagerly(node, store); + } + return NoChange(); +} + + static Reduction ReplaceWithReduction(Node* node, Reduction reduction) { if (reduction.Changed()) { NodeProperties::ReplaceWithValue(node, reduction.replacement()); @@ -612,12 +654,15 @@ Reduction JSTypedLowering::Reduce(Node* node) { return ReplaceWithReduction(node, ReduceJSToStringInput(node->InputAt(0))); case IrOpcode::kJSLoadProperty: - return ReduceJSPropertyLoad(node); + return ReduceJSLoadProperty(node); + case IrOpcode::kJSStoreProperty: + return ReduceJSStoreProperty(node); default: break; } return NoChange(); } -} -} -} // namespace v8::internal::compiler + +} // namespace compiler +} // namespace internal +} // namespace v8 diff --git a/src/compiler/js-typed-lowering.h b/src/compiler/js-typed-lowering.h index 331347c..e2c464a 100644 --- a/src/compiler/js-typed-lowering.h +++ b/src/compiler/js-typed-lowering.h @@ -16,30 +16,28 @@ namespace internal { namespace compiler { // Lowers JS-level operators to simplified operators based on types. -class JSTypedLowering : public Reducer { +class JSTypedLowering FINAL : public Reducer { public: explicit JSTypedLowering(JSGraph* jsgraph) : jsgraph_(jsgraph), simplified_(jsgraph->zone()), machine_(jsgraph->zone()) {} - virtual ~JSTypedLowering() {} + virtual ~JSTypedLowering(); - virtual Reduction Reduce(Node* node); + virtual Reduction Reduce(Node* node) OVERRIDE; JSGraph* jsgraph() { return jsgraph_; } Graph* graph() { return jsgraph_->graph(); } private: friend class JSBinopReduction; - JSGraph* jsgraph_; - SimplifiedOperatorBuilder simplified_; - MachineOperatorBuilder machine_; Reduction ReplaceEagerly(Node* old, Node* node); Reduction ReplaceWith(Node* node) { return Reducer::Replace(node); } Reduction ReduceJSAdd(Node* node); Reduction ReduceJSComparison(Node* node); - Reduction ReduceJSPropertyLoad(Node* node); + Reduction ReduceJSLoadProperty(Node* node); + Reduction ReduceJSStoreProperty(Node* node); Reduction ReduceJSEqual(Node* node, bool invert); Reduction ReduceJSStrictEqual(Node* node, bool invert); Reduction ReduceJSToNumberInput(Node* input); @@ -55,9 +53,14 @@ class JSTypedLowering : public Reducer { CommonOperatorBuilder* common() { return jsgraph_->common(); } SimplifiedOperatorBuilder* simplified() { return &simplified_; } MachineOperatorBuilder* machine() { return &machine_; } + + JSGraph* jsgraph_; + SimplifiedOperatorBuilder simplified_; + MachineOperatorBuilder machine_; }; -} -} -} // namespace v8::internal::compiler + +} // namespace compiler +} // namespace internal +} // namespace v8 #endif // V8_COMPILER_OPERATOR_REDUCERS_H_ diff --git a/test/cctest/compiler/test-run-properties.cc b/test/cctest/compiler/test-run-properties.cc index 8bf0fe9..b1f04c5 100644 --- a/test/cctest/compiler/test-run-properties.cc +++ b/test/cctest/compiler/test-run-properties.cc @@ -69,3 +69,71 @@ TEST(TypedArrayLoad) { // TODO(mstarzinger): Add tests for Float32. // TODO(mstarzinger): Add tests for ClampedUint8. } + + +template +static void TypedArrayStoreHelper(const char* array_type) { + static const uint32_t kValues[] = { + 0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321, + 0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff, + 0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000}; + EmbeddedVector values_buffer; + StringBuilder values_builder(values_buffer.start(), values_buffer.length()); + for (size_t i = 0; i < arraysize(kValues); ++i) { + values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]); + } + + // Note that below source creates two different typed arrays with distinct + // elements kind to get coverage for both access patterns: + // - IsFixedTypedArrayElementsKind(x) + // - IsExternalArrayElementsKind(y) + const char* source = + "(function(a) {" + " var x = (a = new %sArray(%d)); %s;" + " var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);" + " if (!%%HasFixed%sElements(x)) %%AbortJS('x');" + " if (!%%HasExternal%sElements(y)) %%AbortJS('y');" + " function f(a,b) {" + " a = a | 0; b = b | 0;" + " var t = x[a];" + " x[a] = y[b];" + " y[b] = t;" + " t = y[b];" + " y[b] = x[a];" + " x[a] = t;" + " return x[a] + y[b];" + " }" + " return f;" + "})()"; + EmbeddedVector source_buffer; + SNPrintF(source_buffer, source, array_type, arraysize(kValues), + values_buffer.start(), array_type, arraysize(kValues), + values_buffer.start(), array_type, array_type); + + FunctionTester T( + source_buffer.start(), + CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled); + for (size_t i = 0; i < arraysize(kValues); ++i) { + for (size_t j = 0; j < arraysize(kValues); ++j) { + double value_a = static_cast(kValues[i]); + double value_b = static_cast(kValues[j]); + double expected = value_b + value_a; + T.CheckCall(T.Val(expected), T.Val(static_cast(i)), + T.Val(static_cast(j))); + } + } +} + + +TEST(TypedArrayStore) { + FLAG_typed_array_max_size_in_heap = 256; + TypedArrayStoreHelper("Int8"); + TypedArrayStoreHelper("Uint8"); + TypedArrayStoreHelper("Int16"); + TypedArrayStoreHelper("Uint16"); + TypedArrayStoreHelper("Int32"); + TypedArrayStoreHelper("Uint32"); + TypedArrayStoreHelper("Float64"); + // TODO(mstarzinger): Add tests for Float32. + // TODO(mstarzinger): Add tests for ClampedUint8. +}