"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",
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);
kParseRestriction = 1 << 14,
kSerializing = 1 << 15,
kContextSpecializing = 1 << 16,
- kInliningEnabled = 1 << 17
+ kInliningEnabled = 1 << 17,
+ kTypingEnabled = 1 << 18
};
CompilationInfo(Handle<JSFunction> closure, Zone* zone);
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();
--- /dev/null
+// 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_
// 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"
}
+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());
case IrOpcode::kJSToString:
return ReplaceWithReduction(node,
ReduceJSToStringInput(node->InputAt(0)));
+ case IrOpcode::kJSLoadProperty:
+ return ReduceJSPropertyLoad(node);
default:
break;
}
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);
#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"
GraphReplayPrinter::PrintReplay(&graph);
}
- if (FLAG_turbo_types) {
+ if (info()->is_typing_enabled()) {
{
// Type the graph.
PhaseStats typer_stats(info(), PhaseStats::CREATE_GRAPH, "typer");
}
{
// 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");
}
+// 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.
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());
'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',
flags_(flags) {
Compile(function);
const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
- CompilationInfo::kInliningEnabled;
+ CompilationInfo::kInliningEnabled |
+ CompilationInfo::kTypingEnabled;
CHECK_EQ(0, flags_ & ~supported_flags);
}
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());
--- /dev/null
+// 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.
+}
'../../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',