Commit d5f00cf6 authored by kbr@chromium.org's avatar kbr@chromium.org

Add optimized ICs for new CanvasArray types introduced in WebGL

specification under development. This is a follow-on CL to
http://codereview.chromium.org/293023 .

Based on review feedback, defined the behavior of storing NaN and
+/-Infinity into external arrays of integer types as storing 0. Added
test cases. Added fucomi instruction to assembler. Fixed bug in
KeyedLoadIC::GenerateExternalArray when allocation of HeapNumber
failed. Fixed bug in encoding of 16-bit immediate arithmetic
instructions in 64-bit port.

Removed raising of exceptions for negative array indices passed to
external arrays and associated tests. Based on current discussion in
WebGL working group, will probably end up removing the exception
throwing altogether.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3113 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent bb2f8c03
......@@ -1850,6 +1850,14 @@ void Assembler::fucompp() {
}
void Assembler::fucomi(int i) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xDB);
EMIT(0xE8 + i);
}
void Assembler::fucomip() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -702,6 +702,7 @@ class Assembler : public Malloced {
void ftst();
void fucomp(int i);
void fucompp();
void fucomi(int i);
void fucomip();
void fcompp();
void fnstsw_ax();
......
This diff is collapsed.
......@@ -7313,7 +7313,7 @@ static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver,
cast_value = static_cast<ValueType>(int_value);
} else if (value->IsHeapNumber()) {
double double_value = HeapNumber::cast(value)->value();
cast_value = static_cast<ValueType>(double_value);
cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
} else {
// Clamp undefined to zero (default). All other types have been
// converted to a number type further up in the call chain.
......@@ -7365,7 +7365,7 @@ Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
cast_value = static_cast<uint32_t>(int_value);
} else if (value->IsHeapNumber()) {
double double_value = HeapNumber::cast(value)->value();
cast_value = static_cast<uint32_t>(double_value);
cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
} else {
// Clamp undefined to zero (default). All other types have been
// converted to a number type further up in the call chain.
......
......@@ -2580,18 +2580,6 @@ Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
return GetElementOrCharAt(object, index);
}
// If the target object is a JSObject and has an ExternalArray as
// its elements, we need to check for negative indices and report
// exceptions. Indices larger than the array's length will be caught
// elsewhere.
if (key->IsSmi() && Smi::cast(*key)->value() < 0) {
if (object->IsJSObject() &&
JSObject::cast(*object)->HasExternalArrayElements()) {
uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
return Top::Throw(*Factory::NewIndexError(index));
}
}
// Convert the key to a string - possibly by calling back into JavaScript.
Handle<String> name;
if (key->IsString()) {
......@@ -2726,18 +2714,6 @@ Object* Runtime::SetObjectProperty(Handle<Object> object,
return *value;
}
// If the target object is a JSObject and has an ExternalArray as
// its elements, we need to check for negative indices and report
// exceptions. Indices larger than the array's length will be caught
// elsewhere.
if (key->IsSmi() && Smi::cast(*key)->value() < 0) {
if (object->IsJSObject() &&
JSObject::cast(*object)->HasExternalArrayElements()) {
uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
return Top::Throw(*Factory::NewIndexError(index));
}
}
if (key->IsString()) {
Handle<Object> result;
if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
......
......@@ -574,11 +574,11 @@ void Assembler::immediate_arithmetic_op_16(byte subcode,
emit(src.value_);
} else if (dst.is(rax)) {
emit(0x05 | (subcode << 3));
emitl(src.value_);
emitw(src.value_);
} else {
emit(0x81);
emit_modrm(subcode, dst);
emitl(src.value_);
emitw(src.value_);
}
}
......@@ -597,7 +597,7 @@ void Assembler::immediate_arithmetic_op_16(byte subcode,
} else {
emit(0x81);
emit_operand(subcode, dst);
emitl(src.value_);
emitw(src.value_);
}
}
......@@ -2229,6 +2229,14 @@ void Assembler::fucompp() {
}
void Assembler::fucomi(int i) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xDB);
emit(0xE8 + i);
}
void Assembler::fucomip() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -1049,6 +1049,7 @@ class Assembler : public Malloced {
void ftst();
void fucomp(int i);
void fucompp();
void fucomi(int i);
void fucomip();
void fcompp();
......
This diff is collapsed.
......@@ -8197,15 +8197,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
CHECK_EQ(28, result->Int32Value());
// Check out-of-range loads.
result = CompileRun("var caught_exception = false;"
"try {"
" ext_array[-1];"
"} catch (e) {"
" caught_exception = true;"
"}"
"caught_exception;");
CHECK_EQ(true, result->BooleanValue());
i::OS::SNPrintF(test_buf,
"var caught_exception = false;"
"try {"
......@@ -8219,15 +8210,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
CHECK_EQ(true, result->BooleanValue());
// Check out-of-range stores.
result = CompileRun("var caught_exception = false;"
"try {"
" ext_array[-1] = 1;"
"} catch (e) {"
" caught_exception = true;"
"}"
"caught_exception;");
CHECK_EQ(true, result->BooleanValue());
i::OS::SNPrintF(test_buf,
"var caught_exception = false;"
"try {"
......@@ -8240,9 +8222,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
result = CompileRun(test_buf.start());
CHECK_EQ(true, result->BooleanValue());
// TODO(kbr): check what happens during IC misses on the type of the object.
// Re-assign array object halfway through a loop.
// Check other boundary conditions, values and operations.
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[7] = undefined;"
......@@ -8258,9 +8237,39 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
CHECK_EQ(2, result->Int32Value());
CHECK_EQ(2, static_cast<int>(jsobj->GetElement(6)->Number()));
// Result for storing NaNs and +/-Infinity isn't defined for these
// types; they do not have the clamping behavior CanvasPixelArray
// specifies.
if (array_type != v8::kExternalFloatArray) {
// Though the specification doesn't state it, be explicit about
// converting NaNs and +/-Infinity to zero.
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = 5;"
"}"
"for (var i = 0; i < 8; i++) {"
" ext_array[i] = NaN;"
"}"
"ext_array[5];");
CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = 5;"
"}"
"for (var i = 0; i < 8; i++) {"
" ext_array[i] = Infinity;"
"}"
"ext_array[5];");
CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = 5;"
"}"
"for (var i = 0; i < 8; i++) {"
" ext_array[i] = -Infinity;"
"}"
"ext_array[5];");
CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
}
result = CompileRun("ext_array[3] = 33;"
"delete ext_array[3];"
......
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