Preliminary lowering of typed array loads in TF.

R=titzer@chromium.org
TEST=cctest/test-run-properties/TypedArrayLoad

Review URL: https://codereview.chromium.org/516853002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23492 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d6831dbd
......@@ -460,6 +460,7 @@ source_set("v8_base") {
"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",
......
......@@ -139,6 +139,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
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);
......
......@@ -81,7 +81,8 @@ class CompilationInfo {
kParseRestriction = 1 << 14,
kSerializing = 1 << 15,
kContextSpecializing = 1 << 16,
kInliningEnabled = 1 << 17
kInliningEnabled = 1 << 17,
kTypingEnabled = 1 << 18
};
CompilationInfo(Handle<JSFunction> closure, Zone* zone);
......@@ -191,6 +192,10 @@ class CompilationInfo {
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() &&
!is_debug();
......
// 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_
......@@ -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"
......@@ -499,6 +500,43 @@ Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
}
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) {
if (reduction.Changed()) {
NodeProperties::ReplaceWithValue(node, reduction.replacement());
......@@ -573,6 +611,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSToString:
return ReplaceWithReduction(node,
ReduceJSToStringInput(node->InputAt(0)));
case IrOpcode::kJSLoadProperty:
return ReduceJSPropertyLoad(node);
default:
break;
}
......
......@@ -39,6 +39,7 @@ class JSTypedLowering : public Reducer {
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);
......
......@@ -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 @@ Handle<Code> Pipeline::GenerateCode() {
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 @@ Handle<Code> Pipeline::GenerateCode() {
}
{
// 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");
......
......@@ -94,6 +94,55 @@ inline const ElementAccess ElementAccessOf(Operator* op) {
}
// 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
// medium-level operations of V8, including adding numbers, allocating objects,
// indexing into objects and arrays, etc.
......
......@@ -751,7 +751,7 @@ void JSArrayBuffer::JSArrayBufferPrint(OStream& os) { // NOLINT
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());
......
......@@ -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',
......
......@@ -32,7 +32,8 @@ class FunctionTester : public InitializedHandleScope {
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 @@ class FunctionTester : public InitializedHandleScope {
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());
......
// 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.
}
......@@ -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',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment