Revision: 23492
Author:   [email protected]
Date:     Thu Aug 28 14:35:11 2014 UTC
Log:      Preliminary lowering of typed array loads in TF.

[email protected]
TEST=cctest/test-run-properties/TypedArrayLoad

Review URL: https://codereview.chromium.org/516853002
https://code.google.com/p/v8/source/detail?r=23492

Added:
 /branches/bleeding_edge/src/compiler/access-builder.h
 /branches/bleeding_edge/test/cctest/compiler/test-run-properties.cc
Modified:
 /branches/bleeding_edge/BUILD.gn
 /branches/bleeding_edge/src/compiler/js-typed-lowering.cc
 /branches/bleeding_edge/src/compiler/js-typed-lowering.h
 /branches/bleeding_edge/src/compiler/pipeline.cc
 /branches/bleeding_edge/src/compiler/simplified-operator.h
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/compiler.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/test/cctest/cctest.gyp
 /branches/bleeding_edge/test/cctest/compiler/function-tester.h
 /branches/bleeding_edge/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/access-builder.h Thu Aug 28 14:35:11 2014 UTC
@@ -0,0 +1,67 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_ACCESS_BUILDER_H_
+#define V8_COMPILER_ACCESS_BUILDER_H_
+
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// This access builder provides a set of static methods constructing commonly +// used FieldAccess and ElementAccess descriptors. These descriptors server as
+// parameters to simplified load/store operators.
+class AccessBuilder : public AllStatic {
+ public:
+  // Provides access to JSObject::elements() field.
+  static FieldAccess ForJSObjectElements() {
+    return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
+            Type::Internal(), kMachAnyTagged};
+  }
+
+  // Provides access to ExternalArray::external_pointer() field.
+  static FieldAccess ForExternalArrayPointer() {
+ return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
+            Type::UntaggedPtr(), kMachPtr};
+  }
+
+ // Provides access to Fixed{type}TypedArray and External{type}Array elements.
+  static ElementAccess ForTypedArrayElement(ExternalArrayType type,
+                                            bool is_external) {
+    BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
+    int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
+    switch (type) {
+      case kExternalInt8Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt8};
+      case kExternalUint8Array:
+      case kExternalUint8ClampedArray:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint8};
+      case kExternalInt16Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt16};
+      case kExternalUint16Array:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint16};
+      case kExternalInt32Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt32};
+      case kExternalUint32Array:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint32};
+      case kExternalFloat32Array:
+        return {taggedness, header_size, Type::Number(), kRepFloat32};
+      case kExternalFloat64Array:
+        return {taggedness, header_size, Type::Number(), kRepFloat64};
+    }
+    UNREACHABLE();
+    return {kUntaggedBase, 0, Type::None(), kMachNone};
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AccessBuilder);
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_ACCESS_BUILDER_H_
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-properties.cc Thu Aug 28 14:35:11 2014 UTC
@@ -0,0 +1,70 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "test/cctest/compiler/function-tester.h"
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+template <typename U>
+static void TypedArrayLoadHelper(const char* array_type) {
+  const int64_t values[] = {
+ 0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321, + 0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff, + 0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000,
+  };
+  size_t size = arraysize(values);
+  EmbeddedVector<char, 1024> values_buffer;
+ StringBuilder values_builder(values_buffer.start(), values_buffer.length());
+  for (unsigned i = 0; i < size; i++) {
+    values_builder.AddFormatted("a[%d] = 0x%08x;", i, values[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 %1$sArray(%2$d)); %3$s;"
+ " var y = (a = new %1$sArray(%2$d)); %3$s; %%TypedArrayGetBuffer(y);"
+      "  if (!%%HasFixed%1$sElements(x)) %%AbortJS('x');"
+      "  if (!%%HasExternal%1$sElements(y)) %%AbortJS('y');"
+      "  function f(a,b) {"
+      "    a = a | 0; b = b | 0;"
+      "    return x[a] + y[b];"
+      "  }"
+      "  return f;"
+      "})()";
+  EmbeddedVector<char, 1024> source_buffer;
+  SNPrintF(source_buffer, source, array_type, size, values_buffer.start());
+
+  FunctionTester T(
+      source_buffer.start(),
+ CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
+  for (unsigned i = 0; i < size; i++) {
+    for (unsigned j = 0; j < size; j++) {
+      double value_a = static_cast<U>(values[i]);
+      double value_b = static_cast<U>(values[j]);
+      double expected = value_a + value_b;
+      T.CheckCall(T.Val(expected), T.Val(i), T.Val(j));
+    }
+  }
+}
+
+
+TEST(TypedArrayLoad) {
+  FLAG_typed_array_max_size_in_heap = 256;
+  TypedArrayLoadHelper<int8_t>("Int8");
+  TypedArrayLoadHelper<uint8_t>("Uint8");
+  TypedArrayLoadHelper<int16_t>("Int16");
+  TypedArrayLoadHelper<uint16_t>("Uint16");
+  TypedArrayLoadHelper<int32_t>("Int32");
+  TypedArrayLoadHelper<uint32_t>("Uint32");
+  TypedArrayLoadHelper<double>("Float64");
+  // TODO(mstarzinger): Add tests for Float32.
+  // TODO(mstarzinger): Add tests for ClampedUint8.
+}
=======================================
--- /branches/bleeding_edge/BUILD.gn    Wed Aug 27 12:16:36 2014 UTC
+++ /branches/bleeding_edge/BUILD.gn    Thu Aug 28 14:35:11 2014 UTC
@@ -460,6 +460,7 @@
     "src/codegen.h",
     "src/compilation-cache.cc",
     "src/compilation-cache.h",
+    "src/compiler/access-builder.h",
     "src/compiler/ast-graph-builder.cc",
     "src/compiler/ast-graph-builder.h",
     "src/compiler/change-lowering.cc",
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Wed Aug 20 13:05:03 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Thu Aug 28 14:35:11 2014 UTC
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include "src/compiler/access-builder.h"
 #include "src/compiler/graph-inl.h"
 #include "src/compiler/js-typed-lowering.h"
 #include "src/compiler/node-aux-data-inl.h"
@@ -497,6 +498,43 @@
   // TODO(turbofan): js-typed-lowering of ToBoolean(string)
   return NoChange();
 }
+
+
+Reduction JSTypedLowering::ReduceJSPropertyLoad(Node* node) {
+  Node* key = NodeProperties::GetValueInput(node, 1);
+  Node* base = NodeProperties::GetValueInput(node, 0);
+  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 (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
+      base_type->AsConstant()->Value()->IsJSTypedArray()) {
+    // JSLoadProperty(typed-array, int32)
+ 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* value =
+ graph()->NewNode(simplified()->LoadElement(element_access), elements,
+                         key, NodeProperties::GetEffectInput(node));
+    return ReplaceEagerly(node, value);
+  }
+  return NoChange();
+}


 static Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
@@ -573,6 +611,8 @@
     case IrOpcode::kJSToString:
       return ReplaceWithReduction(node,
                                   ReduceJSToStringInput(node->InputAt(0)));
+    case IrOpcode::kJSLoadProperty:
+      return ReduceJSPropertyLoad(node);
     default:
       break;
   }
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.h Thu Aug 14 12:24:37 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-typed-lowering.h Thu Aug 28 14:35:11 2014 UTC
@@ -39,6 +39,7 @@
   Reduction ReplaceWith(Node* node) { return Reducer::Replace(node); }
   Reduction ReduceJSAdd(Node* node);
   Reduction ReduceJSComparison(Node* node);
+  Reduction ReduceJSPropertyLoad(Node* node);
   Reduction ReduceJSEqual(Node* node, bool invert);
   Reduction ReduceJSStrictEqual(Node* node, bool invert);
   Reduction ReduceJSToNumberInput(Node* input);
=======================================
--- /branches/bleeding_edge/src/compiler/pipeline.cc Thu Aug 28 08:39:24 2014 UTC +++ /branches/bleeding_edge/src/compiler/pipeline.cc Thu Aug 28 14:35:11 2014 UTC
@@ -16,11 +16,13 @@
 #include "src/compiler/js-generic-lowering.h"
 #include "src/compiler/js-inlining.h"
 #include "src/compiler/js-typed-lowering.h"
+#include "src/compiler/machine-operator-reducer.h"
 #include "src/compiler/phi-reducer.h"
 #include "src/compiler/register-allocator.h"
 #include "src/compiler/schedule.h"
 #include "src/compiler/scheduler.h"
 #include "src/compiler/simplified-lowering.h"
+#include "src/compiler/simplified-operator-reducer.h"
 #include "src/compiler/typer.h"
 #include "src/compiler/verifier.h"
 #include "src/hydrogen.h"
@@ -213,7 +215,7 @@
     GraphReplayPrinter::PrintReplay(&graph);
   }

-  if (FLAG_turbo_types) {
+  if (info()->is_typing_enabled()) {
     {
       // Type the graph.
       PhaseStats typer_stats(info(), PhaseStats::CREATE_GRAPH, "typer");
@@ -247,15 +249,20 @@
     }
     {
       // Lower changes that have been inserted before.
-      PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
+      PhaseStats lowering_stats(info(), PhaseStats::OPTIMIZATION,
                                 "change lowering");
       SourcePositionTable::Scope pos(&source_positions,
                                      SourcePosition::Unknown());
       Linkage linkage(info());
       MachineOperatorBuilder machine(zone());
+      SimplifiedOperatorReducer simple_reducer(&jsgraph, &machine);
       ChangeLowering lowering(&jsgraph, &linkage, &machine);
+      MachineOperatorReducer mach_reducer(&graph);
       GraphReducer graph_reducer(&graph);
+ // TODO(titzer): Figure out if we should run all reducers at once here.
+      graph_reducer.AddReducer(&simple_reducer);
       graph_reducer.AddReducer(&lowering);
+      graph_reducer.AddReducer(&mach_reducer);
       graph_reducer.ReduceGraph();

       VerifyAndPrintGraph(&graph, "Lowered changes");
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator.h Thu Aug 14 09:19:54 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-operator.h Thu Aug 28 14:35:11 2014 UTC
@@ -92,6 +92,55 @@
          op->opcode() == IrOpcode::kStoreElement);
   return static_cast<Operator1<ElementAccess>*>(op)->parameter();
 }
+
+
+// This access helper provides a set of static methods constructing commonly
+// used FieldAccess and ElementAccess descriptors.
+class Access : public AllStatic {
+ public:
+  // Provides access to JSObject::elements() field.
+  static FieldAccess ForJSObjectElements() {
+    return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
+            Type::Internal(), kMachAnyTagged};
+  }
+
+  // Provides access to ExternalArray::external_pointer() field.
+  static FieldAccess ForExternalArrayPointer() {
+ return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
+            Type::UntaggedPtr(), kMachPtr};
+  }
+
+ // Provides access to Fixed{type}TypedArray and External{type}Array elements.
+  static ElementAccess ForTypedArrayElement(ExternalArrayType type,
+                                            bool is_external) {
+    BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
+    int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
+    switch (type) {
+      case kExternalInt8Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt8};
+      case kExternalUint8Array:
+      case kExternalUint8ClampedArray:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint8};
+      case kExternalInt16Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt16};
+      case kExternalUint16Array:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint16};
+      case kExternalInt32Array:
+        return {taggedness, header_size, Type::Signed32(), kMachInt32};
+      case kExternalUint32Array:
+        return {taggedness, header_size, Type::Unsigned32(), kMachUint32};
+      case kExternalFloat32Array:
+        return {taggedness, header_size, Type::Number(), kRepFloat32};
+      case kExternalFloat64Array:
+        return {taggedness, header_size, Type::Number(), kRepFloat64};
+    }
+    UNREACHABLE();
+    return {kUntaggedBase, 0, Type::None(), kMachNone};
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Access);
+};


 // Interface for building simplified operators, which represent the
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Tue Aug 26 17:04:34 2014 UTC
+++ /branches/bleeding_edge/src/compiler.cc     Thu Aug 28 14:35:11 2014 UTC
@@ -139,6 +139,7 @@
   if (script_->type()->value() == Script::TYPE_NATIVE) MarkAsNative();
   if (isolate_->debug()->is_active()) MarkAsDebug();
   if (FLAG_context_specialization) MarkAsContextSpecializing();
+  if (FLAG_turbo_types) MarkAsTypingEnabled();

   if (!shared_info_.is_null()) {
     DCHECK(strict_mode() == SLOPPY);
=======================================
--- /branches/bleeding_edge/src/compiler.h      Thu Aug 28 08:39:24 2014 UTC
+++ /branches/bleeding_edge/src/compiler.h      Thu Aug 28 14:35:11 2014 UTC
@@ -81,7 +81,8 @@
     kParseRestriction = 1 << 14,
     kSerializing = 1 << 15,
     kContextSpecializing = 1 << 16,
-    kInliningEnabled = 1 << 17
+    kInliningEnabled = 1 << 17,
+    kTypingEnabled = 1 << 18
   };

   CompilationInfo(Handle<JSFunction> closure, Zone* zone);
@@ -190,6 +191,10 @@
   void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }

   bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
+
+  void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
+
+  bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }

   bool IsCodePreAgingActive() const {
     return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Tue Aug 26 16:32:51 2014 UTC +++ /branches/bleeding_edge/src/objects-printer.cc Thu Aug 28 14:35:11 2014 UTC
@@ -751,7 +751,7 @@
 void JSTypedArray::JSTypedArrayPrint(OStream& os) {  // NOLINT
   HeapObject::PrintHeader(os, "JSTypedArray");
   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
-  os << " - buffer =" << Brief(buffer());
+  os << " - buffer = " << Brief(buffer());
   os << "\n - byte_offset = " << Brief(byte_offset());
   os << "\n - byte_length = " << Brief(byte_length());
   os << "\n - length = " << Brief(length());
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.gyp Thu Aug 28 13:17:38 2014 UTC +++ /branches/bleeding_edge/test/cctest/cctest.gyp Thu Aug 28 14:35:11 2014 UTC
@@ -79,6 +79,7 @@
         'compiler/test-run-jsexceptions.cc',
         'compiler/test-run-jsops.cc',
         'compiler/test-run-machops.cc',
+        'compiler/test-run-properties.cc',
         'compiler/test-run-variables.cc',
         'compiler/test-schedule.cc',
         'compiler/test-scheduler.cc',
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/function-tester.h Thu Aug 28 08:47:11 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/function-tester.h Thu Aug 28 14:35:11 2014 UTC
@@ -32,7 +32,8 @@
         flags_(flags) {
     Compile(function);
const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
-                                     CompilationInfo::kInliningEnabled;
+                                     CompilationInfo::kInliningEnabled |
+                                     CompilationInfo::kTypingEnabled;
     CHECK_EQ(0, flags_ & ~supported_flags);
   }

@@ -53,6 +54,9 @@
     if (flags_ & CompilationInfo::kInliningEnabled) {
       info.MarkAsInliningEnabled();
     }
+    if (flags_ & CompilationInfo::kTypingEnabled) {
+      info.MarkAsTypingEnabled();
+    }
     CHECK(Rewriter::Rewrite(&info));
     CHECK(Scope::Analyze(&info));
     CHECK_NE(NULL, info.scope());
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp    Wed Aug 27 12:16:36 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp    Thu Aug 28 14:35:11 2014 UTC
@@ -342,6 +342,7 @@
         '../../src/codegen.h',
         '../../src/compilation-cache.cc',
         '../../src/compilation-cache.h',
+        '../../src/compiler/access-builder.h',
         '../../src/compiler/ast-graph-builder.cc',
         '../../src/compiler/ast-graph-builder.h',
         '../../src/compiler/change-lowering.cc',

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to