Add Crankshaft support for smi-only elements

Review URL: http://codereview.chromium.org/8002019

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9426 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6dee868e
......@@ -3346,6 +3346,13 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
Register scratch = scratch0();
// This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
// conversion, so it deopts in that case.
if (instr->hydrogen()->ValueNeedsSmiCheck()) {
__ tst(value, Operand(kSmiTagMask));
DeoptimizeIf(ne, instr->environment());
}
// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
......
......@@ -3740,7 +3740,9 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
class HStoreKeyedFastElement: public HTemplateInstruction<3> {
public:
HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val) {
HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
ElementsKind elements_kind = FAST_ELEMENTS)
: elements_kind_(elements_kind) {
SetOperandAt(0, obj);
SetOperandAt(1, key);
SetOperandAt(2, val);
......@@ -3757,14 +3759,28 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> {
HValue* object() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* value() { return OperandAt(2); }
bool value_is_smi() {
return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
}
bool NeedsWriteBarrier() {
if (value_is_smi()) {
return false;
} else {
return StoringValueNeedsWriteBarrier(value());
}
}
bool ValueNeedsSmiCheck() {
return value_is_smi();
}
virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
private:
ElementsKind elements_kind_;
};
......
This diff is collapsed.
......@@ -942,6 +942,11 @@ class HGraphBuilder: public AstVisitor {
HValue* val,
ElementsKind elements_kind,
bool is_store);
HInstruction* BuildFastElementAccess(HValue* elements,
HValue* checked_key,
HValue* val,
ElementsKind elements_kind,
bool is_store);
HInstruction* BuildMonomorphicElementAccess(HValue* object,
HValue* key,
......
......@@ -3238,6 +3238,13 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
Register elements = ToRegister(instr->object());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
// This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
// conversion, so it deopts in that case.
if (instr->hydrogen()->ValueNeedsSmiCheck()) {
__ test(value, Immediate(kSmiTagMask));
DeoptimizeIf(not_zero, instr->environment());
}
// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
......
......@@ -1689,6 +1689,7 @@ MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
Code* generic_stub) {
Code* result = NULL;
if (receiver->HasFastElements() ||
receiver->HasFastSmiOnlyElements() ||
receiver->HasExternalArrayElements() ||
receiver->HasFastDoubleElements() ||
receiver->HasDictionaryElements()) {
......
......@@ -443,7 +443,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
for (int i = 0; i < content->length(); i++) {
Object* current = content->get(i);
ASSERT(!current->IsFixedArray());
if (!current->IsSmi()) {
if (!current->IsSmi() && !current->IsTheHole()) {
has_non_smi = true;
}
}
......@@ -467,7 +467,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
content->set(i, *result);
has_non_smi = true;
} else {
if (!current->IsSmi()) {
if (!current->IsSmi() && !current->IsTheHole()) {
has_non_smi = true;
}
}
......@@ -8250,6 +8250,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
// The least significant bit (after untagging) indicates whether the
// function is currently optimized, regardless of reason.
if (!V8::UseCrankshaft()) {
return Smi::FromInt(4); // 4 == "never".
}
......
......@@ -3161,6 +3161,13 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
Register elements = ToRegister(instr->object());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
// This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
// conversion, so it deopts in that case.
if (instr->hydrogen()->ValueNeedsSmiCheck()) {
Condition cc = masm()->CheckSmi(value);
DeoptimizeIf(NegateCondition(cc), instr->environment());
}
// Do the store.
if (instr->key()->IsConstantOperand()) {
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
......
......@@ -125,3 +125,70 @@ assertKind(element_kind.external_unsigned_int_elements, new Uint32Array(23));
assertKind(element_kind.external_float_elements, new Float32Array(7));
assertKind(element_kind.external_double_elements, new Float64Array(0));
assertKind(element_kind.external_pixel_elements, new PixelArray(512));
// Crankshaft support for smi-only array elements.
function monomorphic(array) {
for (var i = 0; i < 3; i++) {
array[i] = i + 10;
}
assertKind(element_kind.fast_smi_only_elements, array);
for (var i = 0; i < 3; i++) {
var a = array[i];
assertEquals(i + 10, a);
}
}
var smi_only = [1, 2, 3];
for (var i = 0; i < 3; i++) monomorphic(smi_only);
%OptimizeFunctionOnNextCall(monomorphic);
monomorphic(smi_only);
function polymorphic(array, expected_kind) {
array[1] = 42;
assertKind(expected_kind, array);
var a = array[1];
assertEquals(42, a);
}
var smis = [1, 2, 3];
var strings = ["one", "two", "three"];
var doubles = [0, 0, 0]; doubles[0] = 1.5; doubles[1] = 2.5; doubles[2] = 3.5;
assertKind(support_smi_only_arrays
? element_kind.fast_double_elements
: element_kind.fast_elements,
doubles);
for (var i = 0; i < 3; i++) {
polymorphic(smis, element_kind.fast_smi_only_elements);
polymorphic(strings, element_kind.fast_elements);
polymorphic(doubles, support_smi_only_arrays
? element_kind.fast_double_elements
: element_kind.fast_elements);
}
%OptimizeFunctionOnNextCall(polymorphic);
polymorphic(smis, element_kind.fast_smi_only_elements);
polymorphic(strings, element_kind.fast_elements);
polymorphic(doubles, support_smi_only_arrays
? element_kind.fast_double_elements
: element_kind.fast_elements);
// Crankshaft support for smi-only elements in dynamic array literals.
function get(foo) { return foo; } // Used to generate dynamic values.
//function crankshaft_test(expected_kind) {
function crankshaft_test() {
var a = [get(1), get(2), get(3)];
assertKind(element_kind.fast_smi_only_elements, a);
var b = [get(1), get(2), get("three")];
assertKind(element_kind.fast_elements, b);
var c = [get(1), get(2), get(3.5)];
// The full code generator doesn't support conversion to fast_double_elements
// yet. Crankshaft does, but only with --smi-only-arrays support.
if ((%GetOptimizationStatus(crankshaft_test) & 1) &&
support_smi_only_arrays) {
assertKind(element_kind.fast_double_elements, c);
} else {
assertKind(element_kind.fast_elements, c);
}
}
for (var i = 0; i < 3; i++) {
crankshaft_test();
}
%OptimizeFunctionOnNextCall(crankshaft_test);
crankshaft_test();
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