Dispatch on ElementsKind rather than ExternalArrayType when generating ICs and Crankshaft code for many element operations. This is preparation to be able to share more code in the various element accessor implementations.
Merge logic to maintain external array and fast element stub caches. BUG=none TEST=none Review URL: http://codereview.chromium.org/7112010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8244 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d5951b8ef9
commit
9f432cd159
@ -1933,13 +1933,15 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
HLoadKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Representation representation(instr->representation());
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
@ -1948,7 +1950,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
// An unsigned int array load might overflow and cause a deopt, make sure it
|
||||
// has an environment.
|
||||
return (array_type == kExternalUnsignedIntArray) ?
|
||||
return (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
|
||||
AssignEnvironment(load_instr) : load_instr;
|
||||
}
|
||||
|
||||
@ -1985,18 +1987,21 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
HStoreKeyedSpecializedArrayElement* instr) {
|
||||
Representation representation(instr->value()->representation());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->external_pointer()->representation().IsExternal());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
bool val_is_temp_register = array_type == kExternalPixelArray ||
|
||||
array_type == kExternalFloatArray;
|
||||
bool val_is_temp_register =
|
||||
elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS;
|
||||
LOperand* val = val_is_temp_register
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
|
@ -1297,8 +1297,8 @@ class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1779,8 +1779,8 @@ class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2611,7 +2611,7 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = no_reg;
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
int constant_key = 0;
|
||||
if (key_is_constant) {
|
||||
@ -2622,18 +2622,19 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
|
||||
if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister result(ToDoubleRegister(instr->result()));
|
||||
Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
|
||||
: Operand(key, LSL, shift_size));
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ vldr(result.low(), scratch0(), 0);
|
||||
__ vcvt_f64_f32(result, result.low());
|
||||
} else { // i.e. array_type == kExternalDoubleArray
|
||||
} else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS
|
||||
__ vldr(result, scratch0(), 0);
|
||||
}
|
||||
} else {
|
||||
@ -2641,24 +2642,24 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? MemOperand(external_pointer, constant_key * (1 << shift_size))
|
||||
: MemOperand(external_pointer, key, LSL, shift_size));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ ldrsb(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ ldrb(result, mem_operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ ldrsh(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ ldrh(result, mem_operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
__ ldr(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ ldr(result, mem_operand);
|
||||
__ cmp(result, Operand(0x80000000));
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
@ -2666,8 +2667,11 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
// happens, and generate code that returns a double rather than int.
|
||||
DeoptimizeIf(cs, instr->environment());
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3423,7 +3427,7 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = no_reg;
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
int constant_key = 0;
|
||||
if (key_is_constant) {
|
||||
@ -3434,18 +3438,19 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
|
||||
if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister value(ToDoubleRegister(instr->value()));
|
||||
Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
|
||||
: Operand(key, LSL, shift_size));
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ vcvt_f32_f64(double_scratch0().low(), value);
|
||||
__ vstr(double_scratch0().low(), scratch0(), 0);
|
||||
} else { // i.e. array_type == kExternalDoubleArray
|
||||
} else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS
|
||||
__ vstr(value, scratch0(), 0);
|
||||
}
|
||||
} else {
|
||||
@ -3453,22 +3458,25 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? MemOperand(external_pointer, constant_key * (1 << shift_size))
|
||||
: MemOperand(external_pointer, key, LSL, shift_size));
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ strb(value, mem_operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ strh(value, mem_operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ str(value, mem_operand);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -3115,13 +3115,20 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedLoadExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(r1,
|
||||
@ -3206,7 +3213,7 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(
|
||||
Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
@ -3215,9 +3222,15 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
// -- lr : return address
|
||||
// -- r3 : scratch
|
||||
// -----------------------------------
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
maybe_stub = KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedStoreExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(r2,
|
||||
@ -3410,82 +3423,38 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
|
||||
JSObject*receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(r1,
|
||||
r2,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
|
||||
JSObject* receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
// -- r1 : name
|
||||
// -- r2 : receiver
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(r2,
|
||||
r3,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
|
||||
static bool IsElementTypeSigned(ExternalArrayType array_type) {
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalShortArray:
|
||||
case kExternalIntArray:
|
||||
static bool IsElementTypeSigned(JSObject::ElementsKind elements_kind) {
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
return true;
|
||||
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
return false;
|
||||
|
||||
default:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
@ -3519,25 +3488,25 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
|
||||
|
||||
Register value = r2;
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ ldrsb(value, MemOperand(r3, key, LSR, 1));
|
||||
break;
|
||||
case kExternalPixelArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ ldrb(value, MemOperand(r3, key, LSR, 1));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ ldrsh(value, MemOperand(r3, key, LSL, 0));
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ ldrh(value, MemOperand(r3, key, LSL, 0));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ ldr(value, MemOperand(r3, key, LSL, 1));
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
__ add(r2, r3, Operand(key, LSL, 1));
|
||||
@ -3546,7 +3515,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ ldr(value, MemOperand(r3, key, LSL, 1));
|
||||
}
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
__ add(r2, r3, Operand(key, LSL, 2));
|
||||
@ -3558,7 +3527,9 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ ldr(r3, MemOperand(r4, Register::kSizeInBytes));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3572,7 +3543,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
// d0: value (if VFP3 is supported)
|
||||
// r2/r3: value (if VFP3 is not supported)
|
||||
|
||||
if (array_type == kExternalIntArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
|
||||
// For the Int and UnsignedInt array types, we need to see whether
|
||||
// the value can be represented in a Smi. If not, we need to convert
|
||||
// it to a HeapNumber.
|
||||
@ -3616,7 +3587,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
||||
__ Ret();
|
||||
}
|
||||
} else if (array_type == kExternalUnsignedIntArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
||||
// The test is different for unsigned int values. Since we need
|
||||
// the value to be in the range of a positive smi, we can't
|
||||
// handle either of the top two bits being set in the value.
|
||||
@ -3681,7 +3652,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ mov(r0, r4);
|
||||
__ Ret();
|
||||
}
|
||||
} else if (array_type == kExternalFloatArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
// For the floating-point array type, we need to always allocate a
|
||||
// HeapNumber.
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
@ -3751,7 +3722,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ mov(r0, r3);
|
||||
__ Ret();
|
||||
}
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
// Allocate a HeapNumber for the result. Don't use r0 and r1 as
|
||||
@ -3808,7 +3779,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- r0 : value
|
||||
// -- r1 : key
|
||||
@ -3842,7 +3813,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// runtime for all other kinds of values.
|
||||
// r3: external array.
|
||||
// r4: key (integer).
|
||||
if (array_type == kExternalPixelArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
// Double to pixel conversion is only implemented in the runtime for now.
|
||||
__ JumpIfNotSmi(value, &slow);
|
||||
} else {
|
||||
@ -3854,29 +3825,29 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// r3: base pointer of external storage.
|
||||
// r4: key (integer).
|
||||
// r5: value (integer).
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
// Clamp the value to [0..255].
|
||||
__ Usat(r5, 8, Operand(r5));
|
||||
__ strb(r5, MemOperand(r3, r4, LSL, 0));
|
||||
break;
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ strb(r5, MemOperand(r3, r4, LSL, 0));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ strh(r5, MemOperand(r3, r4, LSL, 1));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ str(r5, MemOperand(r3, r4, LSL, 2));
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
// Perform int-to-float conversion and store to memory.
|
||||
StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
__ add(r3, r3, Operand(r4, LSL, 3));
|
||||
// r3: effective address of the double element
|
||||
FloatingPointHelper::Destination destination;
|
||||
@ -3897,7 +3868,9 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ str(r7, MemOperand(r3, Register::kSizeInBytes));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3905,7 +3878,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// Entry registers are intact, r0 holds the value which is the return value.
|
||||
__ Ret();
|
||||
|
||||
if (array_type != kExternalPixelArray) {
|
||||
if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
// r3: external array.
|
||||
// r4: index (integer).
|
||||
__ bind(&check_heap_number);
|
||||
@ -3923,7 +3896,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
// vldr requires offset to be a multiple of 4 so we can not
|
||||
// include -kHeapObjectTag into it.
|
||||
__ sub(r5, r0, Operand(kHeapObjectTag));
|
||||
@ -3931,7 +3904,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ add(r5, r3, Operand(r4, LSL, 2));
|
||||
__ vcvt_f32_f64(s0, d0);
|
||||
__ vstr(s0, r5, 0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ sub(r5, r0, Operand(kHeapObjectTag));
|
||||
__ vldr(d0, r5, HeapNumber::kValueOffset);
|
||||
__ add(r5, r3, Operand(r4, LSL, 3));
|
||||
@ -3943,20 +3916,25 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ vldr(d0, r5, HeapNumber::kValueOffset);
|
||||
__ EmitECMATruncate(r5, d0, s2, r6, r7, r9);
|
||||
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ strb(r5, MemOperand(r3, r4, LSL, 0));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ strh(r5, MemOperand(r3, r4, LSL, 1));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ str(r5, MemOperand(r3, r4, LSL, 2));
|
||||
break;
|
||||
default:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3970,7 +3948,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
|
||||
__ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
|
||||
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
Label done, nan_or_infinity_or_zero;
|
||||
static const int kMantissaInHiWordShift =
|
||||
kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
|
||||
@ -4022,14 +4000,14 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
|
||||
__ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
|
||||
__ b(&done);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ add(r7, r3, Operand(r4, LSL, 3));
|
||||
// r7: effective address of destination element.
|
||||
__ str(r6, MemOperand(r7, 0));
|
||||
__ str(r5, MemOperand(r7, Register::kSizeInBytes));
|
||||
__ Ret();
|
||||
} else {
|
||||
bool is_signed_type = IsElementTypeSigned(array_type);
|
||||
bool is_signed_type = IsElementTypeSigned(elements_kind);
|
||||
int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
|
||||
int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
|
||||
|
||||
@ -4076,20 +4054,25 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
|
||||
|
||||
__ bind(&done);
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ strb(r5, MemOperand(r3, r4, LSL, 0));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ strh(r5, MemOperand(r3, r4, LSL, 1));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ str(r5, MemOperand(r3, r4, LSL, 2));
|
||||
break;
|
||||
default:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -607,9 +607,6 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
is_string_access_ = true;
|
||||
} else if (is_monomorphic_) {
|
||||
monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
|
||||
if (monomorphic_receiver_type_->has_external_array_elements()) {
|
||||
set_external_array_type(oracle->GetKeyedLoadExternalArrayType(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,9 +624,6 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
} else if (is_monomorphic_) {
|
||||
// Record receiver type for monomorphic keyed loads.
|
||||
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
|
||||
if (monomorphic_receiver_type_->has_external_array_elements()) {
|
||||
set_external_array_type(oracle->GetKeyedStoreExternalArrayType(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -639,9 +633,6 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
if (is_monomorphic_) {
|
||||
// Record receiver type for monomorphic keyed loads.
|
||||
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
|
||||
if (monomorphic_receiver_type_->has_external_array_elements()) {
|
||||
set_external_array_type(oracle->GetKeyedStoreExternalArrayType(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,17 +261,9 @@ class Expression: public AstNode {
|
||||
return Handle<Map>();
|
||||
}
|
||||
|
||||
ExternalArrayType external_array_type() const {
|
||||
return external_array_type_;
|
||||
}
|
||||
void set_external_array_type(ExternalArrayType array_type) {
|
||||
external_array_type_ = array_type;
|
||||
}
|
||||
|
||||
unsigned id() const { return id_; }
|
||||
|
||||
private:
|
||||
ExternalArrayType external_array_type_;
|
||||
unsigned id_;
|
||||
};
|
||||
|
||||
|
@ -255,12 +255,12 @@ void KeyedStoreFastElementStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadExternalArrayStub::Generate(MacroAssembler* masm) {
|
||||
KeyedLoadStubCompiler::GenerateLoadExternalArray(masm, array_type_);
|
||||
KeyedLoadStubCompiler::GenerateLoadExternalArray(masm, elements_kind_);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreExternalArrayStub::Generate(MacroAssembler* masm) {
|
||||
KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, array_type_);
|
||||
KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, elements_kind_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -975,11 +975,11 @@ class KeyedStoreFastElementStub : public CodeStub {
|
||||
|
||||
class KeyedLoadExternalArrayStub : public CodeStub {
|
||||
public:
|
||||
explicit KeyedLoadExternalArrayStub(ExternalArrayType array_type)
|
||||
: array_type_(array_type) { }
|
||||
explicit KeyedLoadExternalArrayStub(JSObject::ElementsKind elements_kind)
|
||||
: elements_kind_(elements_kind) { }
|
||||
|
||||
Major MajorKey() { return KeyedLoadExternalArray; }
|
||||
int MinorKey() { return array_type_; }
|
||||
int MinorKey() { return elements_kind_; }
|
||||
|
||||
void Generate(MacroAssembler* masm);
|
||||
|
||||
@ -988,17 +988,17 @@ class KeyedLoadExternalArrayStub : public CodeStub {
|
||||
DECLARE_ARRAY_STUB_PRINT(KeyedLoadExternalArrayStub)
|
||||
|
||||
protected:
|
||||
ExternalArrayType array_type_;
|
||||
JSObject::ElementsKind elements_kind_;
|
||||
};
|
||||
|
||||
|
||||
class KeyedStoreExternalArrayStub : public CodeStub {
|
||||
public:
|
||||
explicit KeyedStoreExternalArrayStub(ExternalArrayType array_type)
|
||||
: array_type_(array_type) { }
|
||||
explicit KeyedStoreExternalArrayStub(JSObject::ElementsKind elements_kind)
|
||||
: elements_kind_(elements_kind) { }
|
||||
|
||||
Major MajorKey() { return KeyedStoreExternalArray; }
|
||||
int MinorKey() { return array_type_; }
|
||||
int MinorKey() { return elements_kind_; }
|
||||
|
||||
void Generate(MacroAssembler* masm);
|
||||
|
||||
@ -1007,7 +1007,7 @@ class KeyedStoreExternalArrayStub : public CodeStub {
|
||||
DECLARE_ARRAY_STUB_PRINT(KeyedStoreExternalArrayStub)
|
||||
|
||||
protected:
|
||||
ExternalArrayType array_type_;
|
||||
JSObject::ElementsKind elements_kind_;
|
||||
};
|
||||
|
||||
|
||||
|
16
src/heap.h
16
src/heap.h
@ -182,14 +182,14 @@ inline Heap* _inline_get_heap_();
|
||||
V(value_of_symbol, "valueOf") \
|
||||
V(InitializeVarGlobal_symbol, "InitializeVarGlobal") \
|
||||
V(InitializeConstGlobal_symbol, "InitializeConstGlobal") \
|
||||
V(KeyedLoadSpecializedMonomorphic_symbol, \
|
||||
"KeyedLoadSpecializedMonomorphic") \
|
||||
V(KeyedLoadSpecializedPolymorphic_symbol, \
|
||||
"KeyedLoadSpecializedPolymorphic") \
|
||||
V(KeyedStoreSpecializedMonomorphic_symbol, \
|
||||
"KeyedStoreSpecializedMonomorphic") \
|
||||
V(KeyedStoreSpecializedPolymorphic_symbol, \
|
||||
"KeyedStoreSpecializedPolymorphic") \
|
||||
V(KeyedLoadElementMonomorphic_symbol, \
|
||||
"KeyedLoadElementMonomorphic") \
|
||||
V(KeyedLoadElementPolymorphic_symbol, \
|
||||
"KeyedLoadElementPolymorphic") \
|
||||
V(KeyedStoreElementMonomorphic_symbol, \
|
||||
"KeyedStoreElementMonomorphic") \
|
||||
V(KeyedStoreElementPolymorphic_symbol, \
|
||||
"KeyedStoreElementPolymorphic") \
|
||||
V(stack_overflow_symbol, "kStackOverflowBoilerplate") \
|
||||
V(illegal_access_symbol, "illegal access") \
|
||||
V(out_of_memory_symbol, "out-of-memory") \
|
||||
|
@ -1355,34 +1355,39 @@ void HLoadKeyedSpecializedArrayElement::PrintDataTo(
|
||||
StringStream* stream) {
|
||||
external_pointer()->PrintNameTo(stream);
|
||||
stream->Add(".");
|
||||
switch (array_type()) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind()) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
stream->Add("byte");
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
stream->Add("u_byte");
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
stream->Add("short");
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
stream->Add("u_short");
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
stream->Add("int");
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
stream->Add("u_int");
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
stream->Add("float");
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
stream->Add("double");
|
||||
break;
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
stream->Add("pixel");
|
||||
break;
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
stream->Add("[");
|
||||
key()->PrintNameTo(stream);
|
||||
@ -1435,34 +1440,39 @@ void HStoreKeyedSpecializedArrayElement::PrintDataTo(
|
||||
StringStream* stream) {
|
||||
external_pointer()->PrintNameTo(stream);
|
||||
stream->Add(".");
|
||||
switch (array_type()) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind()) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
stream->Add("byte");
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
stream->Add("u_byte");
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
stream->Add("short");
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
stream->Add("u_short");
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
stream->Add("int");
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
stream->Add("u_int");
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
stream->Add("float");
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
stream->Add("double");
|
||||
break;
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
stream->Add("pixel");
|
||||
break;
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
stream->Add("[");
|
||||
key()->PrintNameTo(stream);
|
||||
|
@ -3474,11 +3474,11 @@ class HLoadKeyedSpecializedArrayElement: public HBinaryOperation {
|
||||
public:
|
||||
HLoadKeyedSpecializedArrayElement(HValue* external_elements,
|
||||
HValue* key,
|
||||
ExternalArrayType array_type)
|
||||
JSObject::ElementsKind elements_kind)
|
||||
: HBinaryOperation(external_elements, key),
|
||||
array_type_(array_type) {
|
||||
if (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray) {
|
||||
elements_kind_(elements_kind) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
set_representation(Representation::Double());
|
||||
} else {
|
||||
set_representation(Representation::Integer32());
|
||||
@ -3500,7 +3500,7 @@ class HLoadKeyedSpecializedArrayElement: public HBinaryOperation {
|
||||
|
||||
HValue* external_pointer() { return OperandAt(0); }
|
||||
HValue* key() { return OperandAt(1); }
|
||||
ExternalArrayType array_type() const { return array_type_; }
|
||||
JSObject::ElementsKind elements_kind() const { return elements_kind_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
|
||||
|
||||
@ -3509,11 +3509,11 @@ class HLoadKeyedSpecializedArrayElement: public HBinaryOperation {
|
||||
if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
|
||||
HLoadKeyedSpecializedArrayElement* cast_other =
|
||||
HLoadKeyedSpecializedArrayElement::cast(other);
|
||||
return array_type_ == cast_other->array_type();
|
||||
return elements_kind_ == cast_other->elements_kind();
|
||||
}
|
||||
|
||||
private:
|
||||
ExternalArrayType array_type_;
|
||||
JSObject::ElementsKind elements_kind_;
|
||||
};
|
||||
|
||||
|
||||
@ -3656,8 +3656,8 @@ class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
|
||||
HStoreKeyedSpecializedArrayElement(HValue* external_elements,
|
||||
HValue* key,
|
||||
HValue* val,
|
||||
ExternalArrayType array_type)
|
||||
: array_type_(array_type) {
|
||||
JSObject::ElementsKind elements_kind)
|
||||
: elements_kind_(elements_kind) {
|
||||
SetFlag(kChangesSpecializedArrayElements);
|
||||
SetOperandAt(0, external_elements);
|
||||
SetOperandAt(1, key);
|
||||
@ -3670,8 +3670,10 @@ class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
|
||||
if (index == 0) {
|
||||
return Representation::External();
|
||||
} else {
|
||||
if (index == 2 && (array_type() == kExternalFloatArray ||
|
||||
array_type() == kExternalDoubleArray)) {
|
||||
bool float_or_double_elements =
|
||||
elements_kind() == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind() == JSObject::EXTERNAL_DOUBLE_ELEMENTS;
|
||||
if (index == 2 && float_or_double_elements) {
|
||||
return Representation::Double();
|
||||
} else {
|
||||
return Representation::Integer32();
|
||||
@ -3682,12 +3684,12 @@ class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
|
||||
HValue* external_pointer() { return OperandAt(0); }
|
||||
HValue* key() { return OperandAt(1); }
|
||||
HValue* value() { return OperandAt(2); }
|
||||
ExternalArrayType array_type() const { return array_type_; }
|
||||
JSObject::ElementsKind elements_kind() const { return elements_kind_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
|
||||
|
||||
private:
|
||||
ExternalArrayType array_type_;
|
||||
JSObject::ElementsKind elements_kind_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3809,7 +3809,7 @@ HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
|
||||
AddInstruction(external_elements);
|
||||
HLoadKeyedSpecializedArrayElement* pixel_array_value =
|
||||
new(zone()) HLoadKeyedSpecializedArrayElement(
|
||||
external_elements, checked_key, expr->external_array_type());
|
||||
external_elements, checked_key, map->elements_kind());
|
||||
return pixel_array_value;
|
||||
}
|
||||
|
||||
@ -3890,34 +3890,38 @@ HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
|
||||
HLoadExternalArrayPointer* external_elements =
|
||||
new(zone()) HLoadExternalArrayPointer(elements);
|
||||
AddInstruction(external_elements);
|
||||
ExternalArrayType array_type = expr->external_array_type();
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray: {
|
||||
JSObject::ElementsKind elements_kind = map->elements_kind();
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
|
||||
HClampToUint8* clamp = new(zone()) HClampToUint8(val);
|
||||
AddInstruction(clamp);
|
||||
val = clamp;
|
||||
break;
|
||||
}
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray: {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
|
||||
HToInt32* floor_val = new(zone()) HToInt32(val);
|
||||
AddInstruction(floor_val);
|
||||
val = floor_val;
|
||||
break;
|
||||
}
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
return new(zone()) HStoreKeyedSpecializedArrayElement(
|
||||
external_elements,
|
||||
checked_key,
|
||||
val,
|
||||
expr->external_array_type());
|
||||
map->elements_kind());
|
||||
}
|
||||
|
||||
|
||||
|
@ -2440,11 +2440,12 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
}
|
||||
|
||||
|
||||
Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type) {
|
||||
Operand LCodeGen::BuildExternalArrayOperand(
|
||||
LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
Register external_pointer_reg = ToRegister(external_pointer);
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
if (key->IsConstantOperand()) {
|
||||
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
||||
if (constant_value & 0xF0000000) {
|
||||
@ -2460,35 +2461,35 @@ Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
instr->key(), elements_kind));
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
__ movss(result, operand);
|
||||
__ cvtss2sd(result, result);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ movdbl(ToDoubleRegister(instr->result()), operand);
|
||||
} else {
|
||||
Register result(ToRegister(instr->result()));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ movsx_b(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ movzx_b(result, operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ movsx_w(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movzx_w(result, operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
__ mov(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ mov(result, operand);
|
||||
__ test(result, Operand(result));
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
@ -2496,8 +2497,11 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
// happens, and generate code that returns a double rather than int.
|
||||
DeoptimizeIf(negative, instr->environment());
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3205,32 +3209,35 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
instr->key(), elements_kind));
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
|
||||
__ movss(operand, xmm0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ movdbl(operand, ToDoubleRegister(instr->value()));
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ mov_b(operand, value);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ mov_w(operand, value);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ mov(operand, value);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ class LCodeGen BASE_EMBEDDED {
|
||||
int ToInteger32(LConstantOperand* op) const;
|
||||
Operand BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type);
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
// Specific math operations - used from DoUnaryMathOperation.
|
||||
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
|
||||
|
@ -1965,13 +1965,15 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
HLoadKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Representation representation(instr->representation());
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
@ -1981,7 +1983,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
// An unsigned int array load might overflow and cause a deopt, make sure it
|
||||
// has an environment.
|
||||
return (array_type == kExternalUnsignedIntArray)
|
||||
return (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS)
|
||||
? AssignEnvironment(load_instr)
|
||||
: load_instr;
|
||||
}
|
||||
@ -2019,21 +2021,23 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
HStoreKeyedSpecializedArrayElement* instr) {
|
||||
Representation representation(instr->value()->representation());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
ASSERT(
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->external_pointer()->representation().IsExternal());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LOperand* val = NULL;
|
||||
if (array_type == kExternalByteArray ||
|
||||
array_type == kExternalUnsignedByteArray ||
|
||||
array_type == kExternalPixelArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_BYTE_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
// We need a byte register in this case for the value.
|
||||
val = UseFixed(instr->value(), eax);
|
||||
} else {
|
||||
|
@ -1318,8 +1318,8 @@ class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1807,8 +1807,8 @@ class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2699,7 +2699,7 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(
|
||||
Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
@ -2707,9 +2707,15 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
maybe_stub = KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedStoreExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(edx,
|
||||
@ -3163,13 +3169,20 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedLoadExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(edx,
|
||||
@ -3351,61 +3364,13 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
|
||||
JSObject*receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(edx,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
|
||||
JSObject* receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(edx,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : key
|
||||
// -- edx : receiver
|
||||
@ -3429,28 +3394,28 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ j(above_equal, &miss_force_generic);
|
||||
__ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
|
||||
// ebx: base pointer of external storage
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
__ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ movsx_w(eax, Operand(ebx, ecx, times_2, 0));
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movzx_w(eax, Operand(ebx, ecx, times_2, 0));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
__ mov(ecx, Operand(ebx, ecx, times_4, 0));
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
__ fld_s(Operand(ebx, ecx, times_4, 0));
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
__ fld_d(Operand(ebx, ecx, times_8, 0));
|
||||
break;
|
||||
default:
|
||||
@ -3463,17 +3428,17 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
// For floating-point array type:
|
||||
// FP(0): value
|
||||
|
||||
if (array_type == kExternalIntArray ||
|
||||
array_type == kExternalUnsignedIntArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
||||
// For the Int and UnsignedInt array types, we need to see whether
|
||||
// the value can be represented in a Smi. If not, we need to convert
|
||||
// it to a HeapNumber.
|
||||
Label box_int;
|
||||
if (array_type == kExternalIntArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
|
||||
__ cmp(ecx, 0xC0000000);
|
||||
__ j(sign, &box_int);
|
||||
} else {
|
||||
ASSERT_EQ(array_type, kExternalUnsignedIntArray);
|
||||
ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
|
||||
// The test is different for unsigned int values. Since we need
|
||||
// the value to be in the range of a positive smi, we can't
|
||||
// handle either of the top two bits being set in the value.
|
||||
@ -3489,12 +3454,12 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
|
||||
// Allocate a HeapNumber for the int and perform int-to-double
|
||||
// conversion.
|
||||
if (array_type == kExternalIntArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
|
||||
__ push(ecx);
|
||||
__ fild_s(Operand(esp, 0));
|
||||
__ pop(ecx);
|
||||
} else {
|
||||
ASSERT(array_type == kExternalUnsignedIntArray);
|
||||
ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
|
||||
// Need to zero-extend the value.
|
||||
// There's no fild variant for unsigned values, so zero-extend
|
||||
// to a 64-bit int manually.
|
||||
@ -3510,8 +3475,8 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ mov(eax, ecx);
|
||||
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
__ ret(0);
|
||||
} else if (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
// For the floating-point array type, we need to always allocate a
|
||||
// HeapNumber.
|
||||
__ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
|
||||
@ -3561,7 +3526,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : key
|
||||
// -- edx : receiver
|
||||
@ -3592,7 +3557,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// edi: elements array
|
||||
// ebx: untagged index
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
if (array_type == kExternalPixelArray)
|
||||
if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS)
|
||||
__ j(not_equal, &slow);
|
||||
else
|
||||
__ j(not_equal, &check_heap_number);
|
||||
@ -3602,8 +3567,8 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ SmiUntag(ecx);
|
||||
__ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
|
||||
// ecx: base pointer of external storage
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
{ // Clamp the value to [0..255].
|
||||
Label done;
|
||||
__ test(ecx, Immediate(0xFFFFFF00));
|
||||
@ -3614,27 +3579,27 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
}
|
||||
__ mov_b(Operand(edi, ebx, times_1, 0), ecx);
|
||||
break;
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ mov_b(Operand(edi, ebx, times_1, 0), ecx);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ mov_w(Operand(edi, ebx, times_2, 0), ecx);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ mov(Operand(edi, ebx, times_4, 0), ecx);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
// Need to perform int-to-float conversion.
|
||||
__ push(ecx);
|
||||
__ fild_s(Operand(esp, 0));
|
||||
__ pop(ecx);
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ fstp_s(Operand(edi, ebx, times_4, 0));
|
||||
} else { // array_type == kExternalDoubleArray.
|
||||
} else { // elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS.
|
||||
__ fstp_d(Operand(edi, ebx, times_8, 0));
|
||||
}
|
||||
break;
|
||||
@ -3645,7 +3610,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ ret(0); // Return the original value.
|
||||
|
||||
// TODO(danno): handle heap number -> pixel array conversion
|
||||
if (array_type != kExternalPixelArray) {
|
||||
if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
__ bind(&check_heap_number);
|
||||
// eax: value
|
||||
// edx: receiver
|
||||
@ -3662,11 +3627,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
|
||||
// ebx: untagged index
|
||||
// edi: base pointer of external storage
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
__ fstp_s(Operand(edi, ebx, times_4, 0));
|
||||
__ ret(0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
__ fstp_d(Operand(edi, ebx, times_8, 0));
|
||||
__ ret(0);
|
||||
@ -3679,14 +3644,14 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// (code-stubs-ia32.cc) is roughly what is needed here though the
|
||||
// conversion failure case does not need to be handled.
|
||||
if (CpuFeatures::IsSupported(SSE2)) {
|
||||
if (array_type != kExternalIntArray &&
|
||||
array_type != kExternalUnsignedIntArray) {
|
||||
if (elements_kind != JSObject::EXTERNAL_INT_ELEMENTS &&
|
||||
elements_kind != JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
||||
ASSERT(CpuFeatures::IsSupported(SSE2));
|
||||
CpuFeatures::Scope scope(SSE2);
|
||||
__ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
// ecx: untagged integer value
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
{ // Clamp the value to [0..255].
|
||||
Label done;
|
||||
__ test(ecx, Immediate(0xFFFFFF00));
|
||||
@ -3697,12 +3662,12 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
}
|
||||
__ mov_b(Operand(edi, ebx, times_1, 0), ecx);
|
||||
break;
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ mov_b(Operand(edi, ebx, times_1, 0), ecx);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ mov_w(Operand(edi, ebx, times_2, 0), ecx);
|
||||
break;
|
||||
default:
|
||||
@ -3775,8 +3740,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : key
|
||||
|
30
src/ic.cc
30
src/ic.cc
@ -1070,10 +1070,10 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
||||
|
||||
String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) {
|
||||
if (ic_state == MONOMORPHIC) {
|
||||
return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
|
||||
return isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
|
||||
} else {
|
||||
ASSERT(ic_state == MEGAMORPHIC);
|
||||
return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
|
||||
return isolate()->heap()->KeyedLoadElementPolymorphic_symbol();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1085,8 +1085,8 @@ MaybeObject* KeyedLoadIC::GetFastElementStubWithoutMapCheck(
|
||||
|
||||
|
||||
MaybeObject* KeyedLoadIC::GetExternalArrayStubWithoutMapCheck(
|
||||
ExternalArrayType array_type) {
|
||||
return KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
return KeyedLoadExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
|
||||
|
||||
@ -1697,8 +1697,8 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
|
||||
return generic_stub;
|
||||
}
|
||||
Code* default_stub = Code::cast(maybe_default_stub);
|
||||
return GetExternalArrayStubWithoutMapCheck(
|
||||
default_stub->external_array_type());
|
||||
Map* first_map = default_stub->FindFirstMap();
|
||||
return GetExternalArrayStubWithoutMapCheck(first_map->elements_kind());
|
||||
} else if (receiver_map->has_fast_elements()) {
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
return GetFastElementStubWithoutMapCheck(is_js_array);
|
||||
@ -1713,14 +1713,10 @@ MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
|
||||
StrictModeFlag strict_mode,
|
||||
Code* generic_stub) {
|
||||
Code* result = NULL;
|
||||
if (receiver->HasExternalArrayElements()) {
|
||||
if (receiver->HasFastElements() ||
|
||||
receiver->HasExternalArrayElements()) {
|
||||
MaybeObject* maybe_stub =
|
||||
isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
|
||||
receiver, is_store, strict_mode);
|
||||
if (!maybe_stub->To(&result)) return maybe_stub;
|
||||
} else if (receiver->map()->has_fast_elements()) {
|
||||
MaybeObject* maybe_stub =
|
||||
isolate()->stub_cache()->ComputeKeyedLoadOrStoreFastElement(
|
||||
isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
|
||||
receiver, is_store, strict_mode);
|
||||
if (!maybe_stub->To(&result)) return maybe_stub;
|
||||
} else {
|
||||
@ -1732,10 +1728,10 @@ MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
|
||||
|
||||
String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
|
||||
if (ic_state == MONOMORPHIC) {
|
||||
return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
|
||||
return isolate()->heap()->KeyedStoreElementMonomorphic_symbol();
|
||||
} else {
|
||||
ASSERT(ic_state == MEGAMORPHIC);
|
||||
return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
|
||||
return isolate()->heap()->KeyedStoreElementPolymorphic_symbol();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1747,8 +1743,8 @@ MaybeObject* KeyedStoreIC::GetFastElementStubWithoutMapCheck(
|
||||
|
||||
|
||||
MaybeObject* KeyedStoreIC::GetExternalArrayStubWithoutMapCheck(
|
||||
ExternalArrayType array_type) {
|
||||
return KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
return KeyedStoreExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
|
||||
|
||||
|
6
src/ic.h
6
src/ic.h
@ -350,7 +350,7 @@ class KeyedIC: public IC {
|
||||
bool is_js_array) = 0;
|
||||
|
||||
virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
|
||||
ExternalArrayType array_type) = 0;
|
||||
JSObject::ElementsKind elements_kind) = 0;
|
||||
|
||||
protected:
|
||||
virtual Code* string_stub() {
|
||||
@ -422,7 +422,7 @@ class KeyedLoadIC: public KeyedIC {
|
||||
bool is_js_array);
|
||||
|
||||
virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
|
||||
ExternalArrayType array_type);
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
|
||||
@ -572,7 +572,7 @@ class KeyedStoreIC: public KeyedIC {
|
||||
bool is_js_array);
|
||||
|
||||
virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
|
||||
ExternalArrayType array_type);
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
|
||||
|
@ -166,21 +166,25 @@ void LPointerMap::PrintTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
int ExternalArrayTypeToShiftSize(ExternalArrayType type) {
|
||||
switch (type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
int ElementsKindToShiftSize(JSObject::ElementsKind elements_kind) {
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
return 0;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
return 1;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
return 2;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
return 3;
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
return kPointerSizeLog2;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
@ -585,7 +585,7 @@ class DeepIterator BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
int ExternalArrayTypeToShiftSize(ExternalArrayType type);
|
||||
int ElementsKindToShiftSize(JSObject::ElementsKind elements_kind);
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -2841,19 +2841,6 @@ void Code::set_check_type(CheckType value) {
|
||||
}
|
||||
|
||||
|
||||
ExternalArrayType Code::external_array_type() {
|
||||
ASSERT(is_keyed_load_stub() || is_keyed_store_stub());
|
||||
byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset);
|
||||
return static_cast<ExternalArrayType>(type);
|
||||
}
|
||||
|
||||
|
||||
void Code::set_external_array_type(ExternalArrayType value) {
|
||||
ASSERT(is_keyed_load_stub() || is_keyed_store_stub());
|
||||
WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value);
|
||||
}
|
||||
|
||||
|
||||
byte Code::unary_op_type() {
|
||||
ASSERT(is_unary_op_stub());
|
||||
return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
|
||||
|
@ -3575,12 +3575,6 @@ class Code: public HeapObject {
|
||||
inline CheckType check_type();
|
||||
inline void set_check_type(CheckType value);
|
||||
|
||||
// [external array type]: For kind KEYED_EXTERNAL_ARRAY_LOAD_IC and
|
||||
// KEYED_EXTERNAL_ARRAY_STORE_IC, identifies the type of external
|
||||
// array that the code stub is specialized for.
|
||||
inline ExternalArrayType external_array_type();
|
||||
inline void set_external_array_type(ExternalArrayType value);
|
||||
|
||||
// [type-recording unary op type]: For all UNARY_OP_IC.
|
||||
inline byte unary_op_type();
|
||||
inline void set_unary_op_type(byte value);
|
||||
|
@ -485,86 +485,7 @@ MaybeObject* StubCache::ComputeStoreField(String* name,
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
|
||||
switch (kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
return kExternalByteArray;
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
return kExternalUnsignedByteArray;
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
return kExternalShortArray;
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
return kExternalUnsignedShortArray;
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
return kExternalIntArray;
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
return kExternalUnsignedIntArray;
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
return kExternalFloatArray;
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
return kExternalDoubleArray;
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
return kExternalPixelArray;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return static_cast<ExternalArrayType>(0);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
|
||||
JSObject* receiver,
|
||||
bool is_store,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(
|
||||
is_store ? Code::KEYED_STORE_IC :
|
||||
Code::KEYED_LOAD_IC,
|
||||
NORMAL,
|
||||
strict_mode);
|
||||
ExternalArrayType array_type =
|
||||
ElementsKindToExternalArrayType(receiver->GetElementsKind());
|
||||
String* name = is_store
|
||||
? isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol()
|
||||
: isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
|
||||
Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
|
||||
if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
|
||||
|
||||
MaybeObject* maybe_new_code = NULL;
|
||||
if (is_store) {
|
||||
ExternalArrayStoreStubCompiler compiler(strict_mode);
|
||||
maybe_new_code = compiler.CompileStore(receiver, array_type);
|
||||
} else {
|
||||
ExternalArrayLoadStubCompiler compiler(strict_mode);
|
||||
maybe_new_code = compiler.CompileLoad(receiver, array_type);
|
||||
}
|
||||
Code* code;
|
||||
if (!maybe_new_code->To(&code)) return maybe_new_code;
|
||||
code->set_external_array_type(array_type);
|
||||
if (is_store) {
|
||||
PROFILE(isolate_,
|
||||
CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG,
|
||||
Code::cast(code), 0));
|
||||
} else {
|
||||
PROFILE(isolate_,
|
||||
CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG,
|
||||
Code::cast(code), 0));
|
||||
}
|
||||
ASSERT(code->IsCode());
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result =
|
||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* StubCache::ComputeKeyedLoadOrStoreFastElement(
|
||||
MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
|
||||
JSObject* receiver,
|
||||
bool is_store,
|
||||
StrictModeFlag strict_mode) {
|
||||
@ -575,18 +496,18 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreFastElement(
|
||||
NORMAL,
|
||||
strict_mode);
|
||||
String* name = is_store
|
||||
? isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol()
|
||||
: isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
|
||||
? isolate()->heap()->KeyedStoreElementMonomorphic_symbol()
|
||||
: isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
|
||||
Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
|
||||
if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
|
||||
|
||||
MaybeObject* maybe_new_code = NULL;
|
||||
if (is_store) {
|
||||
KeyedStoreStubCompiler compiler(strict_mode);
|
||||
maybe_new_code = compiler.CompileStoreFastElement(receiver->map());
|
||||
maybe_new_code = compiler.CompileStoreElement(receiver->map());
|
||||
} else {
|
||||
KeyedLoadStubCompiler compiler;
|
||||
maybe_new_code = compiler.CompileLoadFastElement(receiver->map());
|
||||
maybe_new_code = compiler.CompileLoadElement(receiver->map());
|
||||
}
|
||||
Code* code;
|
||||
if (!maybe_new_code->To(&code)) return maybe_new_code;
|
||||
@ -1923,38 +1844,4 @@ void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayLoadStubCompiler::GetCode() {
|
||||
Object* result;
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC,
|
||||
NORMAL,
|
||||
strict_mode_);
|
||||
{ MaybeObject* maybe_result = GetCodeWithFlags(flags,
|
||||
"ExternalArrayLoadStub");
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
Code* code = Code::cast(result);
|
||||
USE(code);
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayLoadStub"));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayStoreStubCompiler::GetCode() {
|
||||
Object* result;
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC,
|
||||
NORMAL,
|
||||
strict_mode_);
|
||||
{ MaybeObject* maybe_result = GetCodeWithFlags(flags,
|
||||
"ExternalArrayStoreStub");
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
Code* code = Code::cast(result);
|
||||
USE(code);
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayStoreStub"));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -183,15 +183,11 @@ class StubCache {
|
||||
Map* transition,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
|
||||
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreElement(
|
||||
JSObject* receiver,
|
||||
bool is_store,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreFastElement(
|
||||
JSObject* receiver,
|
||||
bool is_store,
|
||||
StrictModeFlag strict_mode);
|
||||
// ---
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ComputeCallField(
|
||||
@ -650,14 +646,14 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
||||
MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
|
||||
MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileLoadFastElement(Map* receiver_map);
|
||||
MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileLoadMegamorphic(
|
||||
MapList* receiver_maps,
|
||||
CodeList* handler_ics);
|
||||
|
||||
static void GenerateLoadExternalArray(MacroAssembler* masm,
|
||||
ExternalArrayType array_type);
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
static void GenerateLoadFastElement(MacroAssembler* masm);
|
||||
|
||||
@ -705,7 +701,7 @@ class KeyedStoreStubCompiler: public StubCompiler {
|
||||
Map* transition,
|
||||
String* name);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileStoreFastElement(Map* receiver_map);
|
||||
MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileStoreMegamorphic(
|
||||
MapList* receiver_maps,
|
||||
@ -715,7 +711,7 @@ class KeyedStoreStubCompiler: public StubCompiler {
|
||||
bool is_js_array);
|
||||
|
||||
static void GenerateStoreExternalArray(MacroAssembler* masm,
|
||||
ExternalArrayType array_type);
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
private:
|
||||
MaybeObject* GetCode(PropertyType type,
|
||||
@ -894,35 +890,6 @@ class CallOptimization BASE_EMBEDDED {
|
||||
CallHandlerInfo* api_call_info_;
|
||||
};
|
||||
|
||||
class ExternalArrayLoadStubCompiler: public StubCompiler {
|
||||
public:
|
||||
explicit ExternalArrayLoadStubCompiler(StrictModeFlag strict_mode)
|
||||
: strict_mode_(strict_mode) { }
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileLoad(
|
||||
JSObject* receiver, ExternalArrayType array_type);
|
||||
|
||||
private:
|
||||
MaybeObject* GetCode();
|
||||
|
||||
StrictModeFlag strict_mode_;
|
||||
};
|
||||
|
||||
|
||||
class ExternalArrayStoreStubCompiler: public StubCompiler {
|
||||
public:
|
||||
explicit ExternalArrayStoreStubCompiler(StrictModeFlag strict_mode)
|
||||
: strict_mode_(strict_mode) {}
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CompileStore(
|
||||
JSObject* receiver, ExternalArrayType array_type);
|
||||
|
||||
private:
|
||||
MaybeObject* GetCode();
|
||||
|
||||
StrictModeFlag strict_mode_;
|
||||
};
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
|
@ -171,20 +171,6 @@ CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
|
||||
return check;
|
||||
}
|
||||
|
||||
ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType(
|
||||
Property* expr) {
|
||||
Handle<Object> stub = GetInfo(expr->id());
|
||||
ASSERT(stub->IsCode());
|
||||
return Code::cast(*stub)->external_array_type();
|
||||
}
|
||||
|
||||
ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType(
|
||||
Expression* expr) {
|
||||
Handle<Object> stub = GetInfo(expr->id());
|
||||
ASSERT(stub->IsCode());
|
||||
return Code::cast(*stub)->external_array_type();
|
||||
}
|
||||
|
||||
Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
|
||||
CheckType check) {
|
||||
JSFunction* function = NULL;
|
||||
|
@ -228,9 +228,6 @@ class TypeFeedbackOracle BASE_EMBEDDED {
|
||||
Handle<String> name,
|
||||
CallKind call_kind);
|
||||
|
||||
ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
|
||||
ExternalArrayType GetKeyedStoreExternalArrayType(Expression* expr);
|
||||
|
||||
CheckType GetCallCheckType(Call* expr);
|
||||
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
|
||||
|
||||
|
@ -2445,11 +2445,12 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
}
|
||||
|
||||
|
||||
Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type) {
|
||||
Operand LCodeGen::BuildExternalArrayOperand(
|
||||
LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
Register external_pointer_reg = ToRegister(external_pointer);
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
if (key->IsConstantOperand()) {
|
||||
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
||||
if (constant_value & 0xF0000000) {
|
||||
@ -2465,35 +2466,35 @@ Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
instr->key(), elements_kind));
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
__ movss(result, operand);
|
||||
__ cvtss2sd(result, result);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ movsd(ToDoubleRegister(instr->result()), operand);
|
||||
} else {
|
||||
Register result(ToRegister(instr->result()));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ movsxbq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
__ movzxbq(result, operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ movsxwq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movzxwq(result, operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
__ movsxlq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ movl(result, operand);
|
||||
__ testl(result, result);
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
@ -2501,8 +2502,11 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
// happens, and generate code that returns a double rather than int.
|
||||
DeoptimizeIf(negative, instr->environment());
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
@ -3189,33 +3193,36 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
instr->key(), elements_kind));
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
XMMRegister value(ToDoubleRegister(instr->value()));
|
||||
__ cvtsd2ss(value, value);
|
||||
__ movss(operand, value);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ movsd(operand, ToDoubleRegister(instr->value()));
|
||||
} else {
|
||||
Register value(ToRegister(instr->value()));
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ movb(operand, value);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movw(operand, value);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ movl(operand, value);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
@ -215,9 +215,10 @@ class LCodeGen BASE_EMBEDDED {
|
||||
|
||||
Register ToRegister(int index) const;
|
||||
XMMRegister ToDoubleRegister(int index) const;
|
||||
Operand BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type);
|
||||
Operand BuildExternalArrayOperand(
|
||||
LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
JSObject::ElementsKind elements_kind);
|
||||
|
||||
// Specific math operations - used from DoUnaryMathOperation.
|
||||
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
|
||||
|
@ -1920,13 +1920,15 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
HLoadKeyedSpecializedArrayElement* instr) {
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
Representation representation(instr->representation());
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
@ -1935,7 +1937,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
// An unsigned int array load might overflow and cause a deopt, make sure it
|
||||
// has an environment.
|
||||
return (array_type == kExternalUnsignedIntArray) ?
|
||||
return (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
|
||||
AssignEnvironment(load_instr) : load_instr;
|
||||
}
|
||||
|
||||
@ -1971,18 +1973,21 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
HStoreKeyedSpecializedArrayElement* instr) {
|
||||
Representation representation(instr->value()->representation());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
JSObject::ElementsKind elements_kind = instr->elements_kind();
|
||||
ASSERT(
|
||||
(representation.IsInteger32() && (array_type != kExternalFloatArray &&
|
||||
array_type != kExternalDoubleArray)) ||
|
||||
(representation.IsDouble() && (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray)));
|
||||
(representation.IsInteger32() &&
|
||||
(elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(representation.IsDouble() &&
|
||||
((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->external_pointer()->representation().IsExternal());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
bool val_is_temp_register = array_type == kExternalPixelArray ||
|
||||
array_type == kExternalFloatArray;
|
||||
bool val_is_temp_register =
|
||||
elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS;
|
||||
LOperand* val = val_is_temp_register
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
|
@ -1297,8 +1297,8 @@ class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1751,8 +1751,8 @@ class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
ExternalArrayType array_type() const {
|
||||
return hydrogen()->array_type();
|
||||
JSObject::ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2530,7 +2530,7 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(
|
||||
Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
@ -2538,9 +2538,15 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
maybe_stub = KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedStoreExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(rdx,
|
||||
@ -2990,13 +2996,20 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
|
||||
MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
MaybeObject* maybe_stub;
|
||||
if (receiver_map->has_fast_elements()) {
|
||||
maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
||||
} else {
|
||||
ASSERT(receiver_map->has_external_array_elements());
|
||||
JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
maybe_stub = KeyedLoadExternalArrayStub(elements_kind).TryGetCode();
|
||||
}
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(rdx,
|
||||
@ -3176,60 +3189,13 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
|
||||
JSObject*receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(rdx,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
|
||||
JSObject* receiver, ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
// -- rcx : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
MaybeObject* maybe_stub =
|
||||
KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
||||
Code* stub;
|
||||
if (!maybe_stub->To(&stub)) return maybe_stub;
|
||||
__ DispatchMap(rdx,
|
||||
Handle<Map>(receiver->map()),
|
||||
Handle<Code>(stub),
|
||||
DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
@ -3256,30 +3222,30 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
// rbx: elements array
|
||||
__ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
||||
// rbx: base pointer of external storage
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
__ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
||||
break;
|
||||
case kExternalPixelArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
__ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
__ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ movl(rcx, Operand(rbx, rcx, times_4, 0));
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
__ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
__ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
|
||||
break;
|
||||
default:
|
||||
@ -3295,7 +3261,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
// xmm0: value as double.
|
||||
|
||||
ASSERT(kSmiValueSize == 32);
|
||||
if (array_type == kExternalUnsignedIntArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
||||
// For the UnsignedInt array type, we need to see whether
|
||||
// the value can be represented in a Smi. If not, we need to convert
|
||||
// it to a HeapNumber.
|
||||
@ -3319,8 +3285,8 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
__ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
|
||||
__ movq(rax, rcx);
|
||||
__ ret(0);
|
||||
} else if (array_type == kExternalFloatArray ||
|
||||
array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
||||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
// For the floating-point array type, we need to always allocate a
|
||||
// HeapNumber.
|
||||
__ AllocateHeapNumber(rcx, rbx, &slow);
|
||||
@ -3363,7 +3329,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
JSObject::ElementsKind elements_kind) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
// -- rcx : key
|
||||
@ -3393,7 +3359,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// rbx: elements array
|
||||
// rdi: untagged key
|
||||
Label check_heap_number;
|
||||
if (array_type == kExternalPixelArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
// Float to pixel conversion is only implemented in the runtime for now.
|
||||
__ JumpIfNotSmi(rax, &slow);
|
||||
} else {
|
||||
@ -3403,8 +3369,8 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
__ SmiToInteger32(rdx, rax);
|
||||
__ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
||||
// rbx: base pointer of external storage
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
{ // Clamp the value to [0..255].
|
||||
Label done;
|
||||
__ testl(rdx, Immediate(0xFFFFFF00));
|
||||
@ -3415,36 +3381,38 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
}
|
||||
__ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
||||
break;
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
__ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
// Need to perform int-to-float conversion.
|
||||
__ cvtlsi2ss(xmm0, rdx);
|
||||
__ movss(Operand(rbx, rdi, times_4, 0), xmm0);
|
||||
break;
|
||||
case kExternalDoubleArray:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
// Need to perform int-to-float conversion.
|
||||
__ cvtlsi2sd(xmm0, rdx);
|
||||
__ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
|
||||
break;
|
||||
default:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
__ ret(0);
|
||||
|
||||
// TODO(danno): handle heap number -> pixel array conversion
|
||||
if (array_type != kExternalPixelArray) {
|
||||
if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
||||
__ bind(&check_heap_number);
|
||||
// rax: value
|
||||
// rcx: key (a smi)
|
||||
@ -3463,11 +3431,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// rdi: untagged index
|
||||
// rbx: base pointer of external storage
|
||||
// top of FPU stack: value
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ cvtsd2ss(xmm0, xmm0);
|
||||
__ movss(Operand(rbx, rdi, times_4, 0), xmm0);
|
||||
__ ret(0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
} else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
__ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
|
||||
__ ret(0);
|
||||
} else {
|
||||
@ -3480,26 +3448,30 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// rdx: value (converted to an untagged integer)
|
||||
// rdi: untagged index
|
||||
// rbx: base pointer of external storage
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
switch (elements_kind) {
|
||||
case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
__ cvttsd2si(rdx, xmm0);
|
||||
__ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
__ cvttsd2si(rdx, xmm0);
|
||||
__ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray: {
|
||||
case JSObject::EXTERNAL_INT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
// Convert to int64, so that NaN and infinities become
|
||||
// 0x8000000000000000, which is zero mod 2^32.
|
||||
__ cvttsd2siq(rdx, xmm0);
|
||||
__ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
||||
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
||||
case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case JSObject::FAST_ELEMENTS:
|
||||
case JSObject::FAST_DOUBLE_ELEMENTS:
|
||||
case JSObject::DICTIONARY_ELEMENTS:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user