kExternalUnsignedShortArray,
kExternalIntArray,
kExternalUnsignedIntArray,
- kExternalFloatArray
+ kExternalFloatArray,
+ kExternalPixelArray
};
/**
}
+namespace {
+
+void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
+ void* data,
+ ExternalArrayType array_type,
+ int length) {
+ i::Handle<i::ExternalArray> array =
+ i::Factory::NewExternalArray(length, array_type, data);
+
+ // If the object already has external elements, create a new, unique
+ // map if the element type is now changing, because assumptions about
+ // generated code based on the receiver's map will be invalid.
+ i::Handle<i::HeapObject> elements(object->elements());
+ bool force_unique_map =
+ elements->map()->IsUndefined() ||
+ !elements->map()->has_external_array_elements() ||
+ elements->map() != i::Heap::MapForExternalArrayType(array_type);
+ if (force_unique_map) {
+ i::Handle<i::Map> external_array_map =
+ i::Factory::NewExternalArrayElementsMap(
+ i::Handle<i::Map>(object->map()));
+ object->set_map(*external_array_map);
+ }
+ object->set_elements(*array);
+}
+
+} // namespace
+
+
void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
ON_BAILOUT("v8::SetElementsToPixelData()", return);
ENTER_V8;
HandleScope scope;
- if (!ApiCheck(length <= i::PixelArray::kMaxLength,
+ if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength,
"v8::Object::SetIndexedPropertiesToPixelData()",
"length exceeds max acceptable value")) {
return;
"JSArray is not supported")) {
return;
}
- i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
- i::Handle<i::Map> pixel_array_map =
- i::Factory::GetPixelArrayElementsMap(i::Handle<i::Map>(self->map()));
- self->set_map(*pixel_array_map);
- self->set_elements(*pixels);
+ PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
}
bool v8::Object::HasIndexedPropertiesInPixelData() {
ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- return self->HasPixelElements();
+ return self->HasExternalPixelElements();
}
uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- if (self->HasPixelElements()) {
- return i::PixelArray::cast(self->elements())->external_pointer();
+ if (self->HasExternalPixelElements()) {
+ return i::ExternalPixelArray::cast(self->elements())->
+ external_pixel_pointer();
} else {
return NULL;
}
int v8::Object::GetIndexedPropertiesPixelDataLength() {
ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- if (self->HasPixelElements()) {
- return i::PixelArray::cast(self->elements())->length();
+ if (self->HasExternalPixelElements()) {
+ return i::ExternalPixelArray::cast(self->elements())->length();
} else {
return -1;
}
}
-
void v8::Object::SetIndexedPropertiesToExternalArrayData(
void* data,
ExternalArrayType array_type,
"JSArray is not supported")) {
return;
}
- i::Handle<i::ExternalArray> array =
- i::Factory::NewExternalArray(length, array_type, data);
- i::Handle<i::Map> slow_map =
- i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
- self->set_map(*slow_map);
- self->set_elements(*array);
+ PrepareExternalArrayElements(self, data, array_type, length);
}
return kExternalUnsignedIntArray;
case i::EXTERNAL_FLOAT_ARRAY_TYPE:
return kExternalFloatArray;
+ case i::EXTERNAL_PIXEL_ARRAY_TYPE:
+ return kExternalPixelArray;
default:
return static_cast<ExternalArrayType>(-1);
}
}
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements_map,
- Register elements,
- Register scratch1,
- Register scratch2,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range) {
- // Register use:
- //
- // receiver - holds the receiver on entry.
- // Unchanged unless 'result' is the same register.
- //
- // key - holds the smi key on entry.
- // Unchanged unless 'result' is the same register.
- //
- // elements - set to be the receiver's elements on exit.
- //
- // elements_map - set to be the map of the receiver's elements
- // on exit.
- //
- // result - holds the result of the pixel array load on exit,
- // tagged as a smi if successful.
- //
- // Scratch registers:
- //
- // scratch1 - used a scratch register in map check, if map
- // check is successful, contains the length of the
- // pixel array, the pointer to external elements and
- // the untagged result.
- //
- // scratch2 - holds the untaged key.
-
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit check
- // to ensure the key is a smi must be added.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
- __ SmiUntag(scratch2, key);
-
- // Verify that the receiver has pixel array elements.
- __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
- __ CheckMap(elements, scratch1, Heap::kPixelArrayMapRootIndex,
- not_pixel_array, true);
-
- // Key must be in range of the pixel array.
- __ ldr(scratch1, FieldMemOperand(elements, PixelArray::kLengthOffset));
- __ cmp(scratch2, scratch1);
- __ b(hs, out_of_range); // unsigned check handles negative keys.
-
- // Perform the indexed load and tag the result as a smi.
- __ ldr(scratch1,
- FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
- __ ldrb(scratch1, MemOperand(scratch1, scratch2));
- __ SmiTag(r0, scratch1);
- __ Ret();
-}
-
-
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register elements_map,
- Register scratch1,
- Register scratch2,
- bool load_elements_from_receiver,
- bool load_elements_map_from_elements,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range) {
- // Register use:
- // receiver - holds the receiver and is unchanged unless the
- // store succeeds.
- // key - holds the key (must be a smi) and is unchanged.
- // value - holds the value (must be a smi) and is unchanged.
- // elements - holds the element object of the receiver on entry if
- // load_elements_from_receiver is false, otherwise used
- // internally to store the pixel arrays elements and
- // external array pointer.
- // elements_map - holds the map of the element object if
- // load_elements_map_from_elements is false, otherwise
- // loaded with the element map.
- //
- Register external_pointer = elements;
- Register untagged_key = scratch1;
- Register untagged_value = scratch2;
-
- if (load_elements_from_receiver) {
- __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
- }
-
- // By passing NULL as not_pixel_array, callers signal that they have already
- // verified that the receiver has pixel array elements.
- if (not_pixel_array != NULL) {
- if (load_elements_map_from_elements) {
- __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
- }
- __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
- __ cmp(elements_map, ip);
- __ b(ne, not_pixel_array);
- } else {
- if (FLAG_debug_code) {
- // Map check should have already made sure that elements is a pixel array.
- __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
- __ cmp(elements_map, ip);
- __ Assert(eq, "Elements isn't a pixel array");
- }
- }
-
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit check
- // to ensure the key is a smi must be added.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
-
- __ SmiUntag(untagged_key, key);
-
- // Perform bounds check.
- __ ldr(scratch2, FieldMemOperand(elements, PixelArray::kLengthOffset));
- __ cmp(untagged_key, scratch2);
- __ b(hs, out_of_range); // unsigned check handles negative keys.
-
- __ JumpIfNotSmi(value, value_not_smi);
- __ SmiUntag(untagged_value, value);
-
- // Clamp the value to [0..255].
- __ Usat(untagged_value, 8, Operand(untagged_value));
- // Get the pointer to the external array. This clobbers elements.
- __ ldr(external_pointer,
- FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
- __ strb(untagged_value, MemOperand(external_pointer, untagged_key));
- __ Ret();
-}
-
-
#undef __
} } // namespace v8::internal
};
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements_map,
- Register elements,
- Register scratch1,
- Register scratch2,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If value is not a smi, the generated
-// code will branch to value_not_smi. If the receiver doesn't have pixel array
-// elements, the generated code will branch to not_pixel_array, unless
-// not_pixel_array is NULL, in which case the caller must ensure that the
-// receiver has pixel array elements. If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range. If
-// load_elements_from_receiver is true, then the elements of receiver is loaded
-// into elements, otherwise elements is assumed to already be the receiver's
-// elements. If load_elements_map_from_elements is true, elements_map is loaded
-// from elements, otherwise it is assumed to already contain the element map.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register elements_map,
- Register scratch1,
- Register scratch2,
- bool load_elements_from_receiver,
- bool load_elements_map_from_elements,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range);
-
} } // namespace v8::internal
#endif // V8_ARM_CODE_STUBS_ARM_H_
// -- r1 : receiver
// -----------------------------------
Label slow, check_string, index_smi, index_string, property_array_property;
- Label check_pixel_array, probe_dictionary, check_number_dictionary;
+ Label probe_dictionary, check_number_dictionary;
Register key = r0;
Register receiver = r1;
// now in r2.
__ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset));
__ tst(r3, Operand(1 << Map::kHasFastElements));
- __ b(eq, &check_pixel_array);
+ __ b(eq, &check_number_dictionary);
GenerateFastArrayLoad(
masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
__ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
__ Ret();
- // Check whether the elements is a pixel array.
- // r0: key
- // r1: receiver
- __ bind(&check_pixel_array);
-
- GenerateFastPixelArrayLoad(masm,
- r1,
- r0,
- r3,
- r4,
- r2,
- r5,
- r0,
- &check_number_dictionary,
- NULL,
- &slow);
-
__ bind(&check_number_dictionary);
+ __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
+ __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
+
// Check whether the elements is a number dictionary.
// r0: key
// r3: elements map
// -- r2 : receiver
// -- lr : return address
// -----------------------------------
- Label slow, fast, array, extra, check_pixel_array;
+ Label slow, fast, array, extra;
// Register usage.
Register value = r0;
__ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
__ cmp(r4, ip);
- __ b(ne, &check_pixel_array);
+ __ b(ne, &slow);
// Check array bounds. Both the key and the length of FixedArray are smis.
__ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
__ cmp(key, Operand(ip));
// r2: receiver.
GenerateRuntimeSetProperty(masm, strict_mode);
- // Check whether the elements is a pixel array.
- // r4: elements map.
- __ bind(&check_pixel_array);
- GenerateFastPixelArrayStore(masm,
- r2,
- r1,
- r0,
- elements,
- r4,
- r5,
- r6,
- false,
- false,
- NULL,
- &slow,
- &slow,
- &slow);
-
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
// element to the array by writing to array[array.length].
}
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+ HExternalArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LPixelArrayLength(array));
+ return DefineAsRegister(new LExternalArrayLength(array));
}
}
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
- HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+ HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+ return DefineAsRegister(new LLoadExternalArrayPointer(input));
}
LInstruction* LChunkBuilder::DoStorePixelArrayElement(
HStorePixelArrayElement* instr) {
- Abort("DoStorePixelArrayElement not implemented");
- return NULL;
+ ASSERT(instr->value()->representation().IsInteger32());
+ ASSERT(instr->external_pointer()->representation().IsExternal());
+ ASSERT(instr->key()->representation().IsInteger32());
+
+ LOperand* external_pointer = UseRegister(instr->external_pointer());
+ LOperand* value = UseTempRegister(instr->value()); // changed by clamp.
+ LOperand* key = UseRegister(instr->key());
+
+ return new LStorePixelArrayElement(external_pointer, key, value);
}
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(ExternalArrayLength) \
V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadExternalArrayPointer) \
V(LoadFunctionPrototype) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(LoadPixelArrayElement) \
- V(LoadPixelArrayExternalPointer) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
- V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
V(StoreNamedGeneric) \
+ V(StorePixelArrayElement) \
V(StringCharCodeAt) \
V(StringLength) \
V(SubI) \
};
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LPixelArrayLength(LOperand* value) {
+ explicit LExternalArrayLength(LOperand* value) {
inputs_[0] = value;
}
- DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
- DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+ DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
};
};
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ explicit LLoadExternalArrayPointer(LOperand* object) {
inputs_[0] = object;
}
- DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
- "load-pixel-array-external-pointer")
+ DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+ "load-external-array-pointer")
};
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
virtual void PrintDataTo(StringStream* stream);
LOperand* value() { return inputs_[2]; }
};
+class LStorePixelArrayElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+ LStorePixelArrayElement(LOperand* external_pointer,
+ LOperand* key,
+ LOperand* val) {
+ inputs_[0] = external_pointer;
+ inputs_[1] = key;
+ inputs_[2] = val;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
+ "store-pixel-array-element")
+ DECLARE_HYDROGEN_ACCESSOR(StorePixelArrayElement)
+
+ LOperand* external_pointer() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+ LOperand* value() { return inputs_[2]; }
+};
class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
public:
}
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->InputAt(0));
- __ ldr(result, FieldMemOperand(array, PixelArray::kLengthOffset));
+ __ ldr(result, FieldMemOperand(array, ExternalArray::kLengthOffset));
}
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
__ cmp(scratch, ip);
__ b(eq, &done);
- __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+ __ LoadRoot(ip, Heap::kExternalPixelArrayMapRootIndex);
__ cmp(scratch, ip);
__ b(eq, &done);
__ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
}
-void LCodeGen::DoLoadPixelArrayExternalPointer(
- LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+ LLoadExternalArrayPointer* instr) {
Register to_reg = ToRegister(instr->result());
Register from_reg = ToRegister(instr->InputAt(0));
- __ ldr(to_reg, FieldMemOperand(from_reg, PixelArray::kExternalPointerOffset));
+ __ ldr(to_reg, FieldMemOperand(from_reg,
+ ExternalArray::kExternalPointerOffset));
}
void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
- Register external_elements = ToRegister(instr->external_pointer());
+ Register external_pointer = ToRegister(instr->external_pointer());
Register key = ToRegister(instr->key());
Register result = ToRegister(instr->result());
// Load the result.
- __ ldrb(result, MemOperand(external_elements, key));
+ __ ldrb(result, MemOperand(external_pointer, key));
}
}
+void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+ Register external_pointer = ToRegister(instr->external_pointer());
+ Register key = ToRegister(instr->key());
+ Register value = ToRegister(instr->value());
+
+ // Clamp the value to [0..255].
+ __ Usat(value, 8, Operand(value));
+ __ strb(value, MemOperand(external_pointer, key, LSL, 0));
+}
+
+
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(r2));
ASSERT(ToRegister(instr->key()).is(r1));
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false);
-
- GenerateFastPixelArrayLoad(masm(),
- r1,
- r0,
- r2,
- r3,
- r4,
- r5,
- r0,
- &miss,
- &miss,
- &miss);
-
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
int index,
Map* transition,
}
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
- JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : key
- // -- r2 : receiver
- // -- r3 : scratch
- // -- r4 : scratch
- // -- r5 : scratch
- // -- r6 : scratch
- // -- lr : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false);
-
- GenerateFastPixelArrayStore(masm(),
- r2,
- r1,
- r0,
- r3,
- r4,
- r5,
- r6,
- true,
- true,
- &miss,
- &miss,
- NULL,
- &miss);
-
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
// ----------- S t a t e -------------
// -- r0 : argc
MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject* receiver_object,
+ ExternalArrayType array_type,
+ Code::Flags flags) {
// ---------- S t a t e --------------
// -- lr : return address
// -- r0 : key
// Check that the key is a smi.
__ JumpIfNotSmi(key, &slow);
- // Check that the object is a JS object. Load map into r2.
- __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE);
- __ b(lt, &slow);
-
- // Check that the receiver does not require access checks. We need
- // to check this explicitly since this generic stub does not perform
- // map checks.
- __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
- __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+ // Make sure that we've got the right map.
+ __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
__ b(ne, &slow);
- // Check that the elements array is the appropriate type of
- // ExternalArray.
__ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
- __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
- __ cmp(r2, ip);
- __ b(ne, &slow);
+ // r3: elements array
// Check that the index is in range.
__ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
// Unsigned comparison catches both negative and too-large values.
__ b(lo, &slow);
- // r3: elements array
__ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
// r3: base pointer of external storage
case kExternalByteArray:
__ ldrsb(value, MemOperand(r3, key, LSR, 1));
break;
+ case kExternalPixelArray:
case kExternalUnsignedByteArray:
__ ldrb(value, MemOperand(r3, key, LSR, 1));
break;
MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject* receiver_object,
+ ExternalArrayType array_type,
+ Code::Flags flags) {
// ---------- S t a t e --------------
// -- r0 : value
// -- r1 : key
// Check that the object isn't a smi.
__ JumpIfSmi(receiver, &slow);
- // Check that the object is a JS object. Load map into r3.
- __ CompareObjectType(receiver, r3, r4, FIRST_JS_OBJECT_TYPE);
- __ b(le, &slow);
-
- // Check that the receiver does not require access checks. We need
- // to do this because this generic stub does not perform map checks.
- __ ldrb(ip, FieldMemOperand(r3, Map::kBitFieldOffset));
- __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
+ // Make sure that we've got the right map.
+ __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
__ b(ne, &slow);
+ __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
+
// Check that the key is a smi.
__ JumpIfNotSmi(key, &slow);
- // Check that the elements array is the appropriate type of ExternalArray.
- __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
- __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
- __ cmp(r4, ip);
- __ b(ne, &slow);
-
- // Check that the index is in range.
- __ mov(r4, Operand(key, ASR, kSmiTagSize)); // Untag the index.
+ // Check that the index is in range
+ __ SmiUntag(r4, key);
__ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
__ cmp(r4, ip);
// Unsigned comparison catches both negative and too-large values.
// runtime for all other kinds of values.
// r3: external array.
// r4: key (integer).
- __ JumpIfNotSmi(value, &check_heap_number);
- __ mov(r5, Operand(value, ASR, kSmiTagSize)); // Untag the value.
+ if (array_type == kExternalPixelArray) {
+ // Double to pixel conversion is only implemented in the runtime for now.
+ __ JumpIfNotSmi(value, &slow);
+ } else {
+ __ JumpIfNotSmi(value, &check_heap_number);
+ }
+ __ SmiUntag(r5, value);
__ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
// r3: base pointer of external storage.
// r4: key (integer).
// r5: value (integer).
switch (array_type) {
+ case kExternalPixelArray:
+ // Clamp the value to [0..255].
+ __ Usat(r5, 8, Operand(r5));
+ __ strb(r5, MemOperand(r3, r4, LSL, 0));
+ break;
case kExternalByteArray:
case kExternalUnsignedByteArray:
__ strb(r5, MemOperand(r3, r4, LSL, 0));
// Entry registers are intact, r0 holds the value which is the return value.
__ Ret();
+ if (array_type != kExternalPixelArray) {
+ // r3: external array.
+ // r4: index (integer).
+ __ bind(&check_heap_number);
+ __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
+ __ b(ne, &slow);
- // r3: external array.
- // r4: index (integer).
- __ bind(&check_heap_number);
- __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
- __ b(ne, &slow);
+ __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
- __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
-
- // r3: base pointer of external storage.
- // r4: key (integer).
+ // r3: base pointer of external storage.
+ // r4: key (integer).
- // The WebGL specification leaves the behavior of storing NaN and
- // +/-Infinity into integer arrays basically undefined. For more
- // reproducible behavior, convert these to zero.
- if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
+ // The WebGL specification leaves the behavior of storing NaN and
+ // +/-Infinity into integer arrays basically undefined. For more
+ // reproducible behavior, convert these to zero.
+ if (CpuFeatures::IsSupported(VFP3)) {
+ CpuFeatures::Scope scope(VFP3);
- if (array_type == kExternalFloatArray) {
- // vldr requires offset to be a multiple of 4 so we can not
- // include -kHeapObjectTag into it.
- __ sub(r5, r0, Operand(kHeapObjectTag));
- __ vldr(d0, r5, HeapNumber::kValueOffset);
- __ add(r5, r3, Operand(r4, LSL, 2));
- __ vcvt_f32_f64(s0, d0);
- __ vstr(s0, r5, 0);
- } else {
- // Need to perform float-to-int conversion.
- // Test for NaN or infinity (both give zero).
- __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
-
- // Hoisted load. vldr requires offset to be a multiple of 4 so we can not
- // include -kHeapObjectTag into it.
- __ sub(r5, value, Operand(kHeapObjectTag));
- __ vldr(d0, r5, HeapNumber::kValueOffset);
-
- __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
- // NaNs and Infinities have all-one exponents so they sign extend to -1.
- __ cmp(r6, Operand(-1));
- __ mov(r5, Operand(0), LeaveCC, eq);
-
- // Not infinity or NaN simply convert to int.
- if (IsElementTypeSigned(array_type)) {
- __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
+ if (array_type == kExternalFloatArray) {
+ // vldr requires offset to be a multiple of 4 so we can not
+ // include -kHeapObjectTag into it.
+ __ sub(r5, r0, Operand(kHeapObjectTag));
+ __ vldr(d0, r5, HeapNumber::kValueOffset);
+ __ add(r5, r3, Operand(r4, LSL, 2));
+ __ vcvt_f32_f64(s0, d0);
+ __ vstr(s0, r5, 0);
} else {
- __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
- }
- __ vmov(r5, s0, ne);
-
- switch (array_type) {
- case kExternalByteArray:
- case kExternalUnsignedByteArray:
- __ strb(r5, MemOperand(r3, r4, LSL, 0));
- break;
- case kExternalShortArray:
- case kExternalUnsignedShortArray:
- __ strh(r5, MemOperand(r3, r4, LSL, 1));
- break;
- case kExternalIntArray:
- case kExternalUnsignedIntArray:
- __ str(r5, MemOperand(r3, r4, LSL, 2));
- break;
- default:
- UNREACHABLE();
- break;
+ // Need to perform float-to-int conversion.
+ // Test for NaN or infinity (both give zero).
+ __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
+
+ // Hoisted load. vldr requires offset to be a multiple of 4 so we can
+ // not include -kHeapObjectTag into it.
+ __ sub(r5, value, Operand(kHeapObjectTag));
+ __ vldr(d0, r5, HeapNumber::kValueOffset);
+
+ __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+ // NaNs and Infinities have all-one exponents so they sign extend to -1.
+ __ cmp(r6, Operand(-1));
+ __ mov(r5, Operand(0), LeaveCC, eq);
+
+ // Not infinity or NaN simply convert to int.
+ if (IsElementTypeSigned(array_type)) {
+ __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
+ } else {
+ __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
+ }
+ __ vmov(r5, s0, ne);
+
+ switch (array_type) {
+ case kExternalByteArray:
+ case kExternalUnsignedByteArray:
+ __ strb(r5, MemOperand(r3, r4, LSL, 0));
+ break;
+ case kExternalShortArray:
+ case kExternalUnsignedShortArray:
+ __ strh(r5, MemOperand(r3, r4, LSL, 1));
+ break;
+ case kExternalIntArray:
+ case kExternalUnsignedIntArray:
+ __ str(r5, MemOperand(r3, r4, LSL, 2));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
}
- }
-
- // Entry registers are intact, r0 holds the value which is the return value.
- __ Ret();
- } else {
- // VFP3 is not available do manual conversions.
- __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
- __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
-
- if (array_type == kExternalFloatArray) {
- Label done, nan_or_infinity_or_zero;
- static const int kMantissaInHiWordShift =
- kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
- static const int kMantissaInLoWordShift =
- kBitsPerInt - kMantissaInHiWordShift;
-
- // Test for all special exponent values: zeros, subnormal numbers, NaNs
- // and infinities. All these should be converted to 0.
- __ mov(r7, Operand(HeapNumber::kExponentMask));
- __ and_(r9, r5, Operand(r7), SetCC);
- __ b(eq, &nan_or_infinity_or_zero);
-
- __ teq(r9, Operand(r7));
- __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
- __ b(eq, &nan_or_infinity_or_zero);
-
- // Rebias exponent.
- __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
- __ add(r9,
- r9,
- Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
-
- __ cmp(r9, Operand(kBinary32MaxExponent));
- __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
- __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
- __ b(gt, &done);
-
- __ cmp(r9, Operand(kBinary32MinExponent));
- __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
- __ b(lt, &done);
-
- __ and_(r7, r5, Operand(HeapNumber::kSignMask));
- __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
- __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
- __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
- __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
-
- __ bind(&done);
- __ str(r5, MemOperand(r3, r4, LSL, 2));
// Entry registers are intact, r0 holds the value which is the return
// value.
__ Ret();
-
- __ bind(&nan_or_infinity_or_zero);
- __ and_(r7, r5, Operand(HeapNumber::kSignMask));
- __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
- __ orr(r9, r9, r7);
- __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
- __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
- __ b(&done);
} else {
- bool is_signed_type = IsElementTypeSigned(array_type);
- int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
- int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
-
- Label done, sign;
-
- // Test for all special exponent values: zeros, subnormal numbers, NaNs
- // and infinities. All these should be converted to 0.
- __ mov(r7, Operand(HeapNumber::kExponentMask));
- __ and_(r9, r5, Operand(r7), SetCC);
- __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
- __ b(eq, &done);
-
- __ teq(r9, Operand(r7));
- __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
- __ b(eq, &done);
-
- // Unbias exponent.
- __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
- __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
- // If exponent is negative then result is 0.
- __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
- __ b(mi, &done);
-
- // If exponent is too big then result is minimal value.
- __ cmp(r9, Operand(meaningfull_bits - 1));
- __ mov(r5, Operand(min_value), LeaveCC, ge);
- __ b(ge, &done);
-
- __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
- __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
- __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
-
- __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
- __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
- __ b(pl, &sign);
-
- __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
- __ mov(r5, Operand(r5, LSL, r9));
- __ rsb(r9, r9, Operand(meaningfull_bits));
- __ orr(r5, r5, Operand(r6, LSR, r9));
-
- __ bind(&sign);
- __ teq(r7, Operand(0, RelocInfo::NONE));
- __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
-
- __ bind(&done);
- switch (array_type) {
- case kExternalByteArray:
- case kExternalUnsignedByteArray:
- __ strb(r5, MemOperand(r3, r4, LSL, 0));
- break;
- case kExternalShortArray:
- case kExternalUnsignedShortArray:
- __ strh(r5, MemOperand(r3, r4, LSL, 1));
- break;
- case kExternalIntArray:
- case kExternalUnsignedIntArray:
- __ str(r5, MemOperand(r3, r4, LSL, 2));
- break;
- default:
- UNREACHABLE();
- break;
+ // VFP3 is not available do manual conversions.
+ __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
+ __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
+
+ if (array_type == kExternalFloatArray) {
+ Label done, nan_or_infinity_or_zero;
+ static const int kMantissaInHiWordShift =
+ kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
+
+ static const int kMantissaInLoWordShift =
+ kBitsPerInt - kMantissaInHiWordShift;
+
+ // Test for all special exponent values: zeros, subnormal numbers, NaNs
+ // and infinities. All these should be converted to 0.
+ __ mov(r7, Operand(HeapNumber::kExponentMask));
+ __ and_(r9, r5, Operand(r7), SetCC);
+ __ b(eq, &nan_or_infinity_or_zero);
+
+ __ teq(r9, Operand(r7));
+ __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
+ __ b(eq, &nan_or_infinity_or_zero);
+
+ // Rebias exponent.
+ __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
+ __ add(r9,
+ r9,
+ Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
+
+ __ cmp(r9, Operand(kBinary32MaxExponent));
+ __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
+ __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
+ __ b(gt, &done);
+
+ __ cmp(r9, Operand(kBinary32MinExponent));
+ __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
+ __ b(lt, &done);
+
+ __ and_(r7, r5, Operand(HeapNumber::kSignMask));
+ __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+ __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
+ __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
+ __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
+
+ __ bind(&done);
+ __ str(r5, MemOperand(r3, r4, LSL, 2));
+ // Entry registers are intact, r0 holds the value which is the return
+ // value.
+ __ Ret();
+
+ __ bind(&nan_or_infinity_or_zero);
+ __ and_(r7, r5, Operand(HeapNumber::kSignMask));
+ __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+ __ orr(r9, r9, r7);
+ __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
+ __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
+ __ b(&done);
+ } else {
+ bool is_signed_type = IsElementTypeSigned(array_type);
+ int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
+ int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
+
+ Label done, sign;
+
+ // Test for all special exponent values: zeros, subnormal numbers, NaNs
+ // and infinities. All these should be converted to 0.
+ __ mov(r7, Operand(HeapNumber::kExponentMask));
+ __ and_(r9, r5, Operand(r7), SetCC);
+ __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+ __ b(eq, &done);
+
+ __ teq(r9, Operand(r7));
+ __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+ __ b(eq, &done);
+
+ // Unbias exponent.
+ __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
+ __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
+ // If exponent is negative then result is 0.
+ __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
+ __ b(mi, &done);
+
+ // If exponent is too big then result is minimal value.
+ __ cmp(r9, Operand(meaningfull_bits - 1));
+ __ mov(r5, Operand(min_value), LeaveCC, ge);
+ __ b(ge, &done);
+
+ __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
+ __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+ __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
+
+ __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
+ __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
+ __ b(pl, &sign);
+
+ __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
+ __ mov(r5, Operand(r5, LSL, r9));
+ __ rsb(r9, r9, Operand(meaningfull_bits));
+ __ orr(r5, r5, Operand(r6, LSR, r9));
+
+ __ bind(&sign);
+ __ teq(r7, Operand(0, RelocInfo::NONE));
+ __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
+
+ __ bind(&done);
+ switch (array_type) {
+ case kExternalByteArray:
+ case kExternalUnsignedByteArray:
+ __ strb(r5, MemOperand(r3, r4, LSL, 0));
+ break;
+ case kExternalShortArray:
+ case kExternalUnsignedShortArray:
+ __ strh(r5, MemOperand(r3, r4, LSL, 1));
+ break;
+ case kExternalIntArray:
+ case kExternalUnsignedIntArray:
+ __ str(r5, MemOperand(r3, r4, LSL, 2));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
}
}
}
}
} else if (is_monomorphic_) {
monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
+ if (monomorphic_receiver_type_->has_external_array_elements()) {
+ SetExternalArrayType(oracle->GetKeyedLoadExternalArrayType(this));
+ }
}
}
} 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()) {
+ SetExternalArrayType(oracle->GetKeyedStoreExternalArrayType(this));
+ }
}
}
}
bool is_arguments_access() const { return is_arguments_access_; }
+ ExternalArrayType GetExternalArrayType() const { return array_type_; }
+ void SetExternalArrayType(ExternalArrayType array_type) {
+ array_type_ = array_type;
+ }
+
// Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual bool IsMonomorphic() { return is_monomorphic_; }
bool is_function_prototype_ : 1;
bool is_arguments_access_ : 1;
Handle<Map> monomorphic_receiver_type_;
+ ExternalArrayType array_type_;
// Dummy property used during preparsing.
static Property this_property_;
virtual Handle<Map> GetMonomorphicReceiverType() {
return monomorphic_receiver_type_;
}
+ ExternalArrayType GetExternalArrayType() const { return array_type_; }
+ void SetExternalArrayType(ExternalArrayType array_type) {
+ array_type_ = array_type;
+ }
// Bailout support.
int CompoundLoadId() const { return compound_load_id_; }
bool is_monomorphic_;
ZoneMapList* receiver_types_;
Handle<Map> monomorphic_receiver_type_;
+ ExternalArrayType array_type_;
};
}
-Handle<PixelArray> Factory::NewPixelArray(int length,
- uint8_t* external_pointer,
- PretenureFlag pretenure) {
- ASSERT(0 <= length);
- CALL_HEAP_FUNCTION(Heap::AllocatePixelArray(length,
- external_pointer,
- pretenure), PixelArray);
-}
-
-
Handle<ExternalArray> Factory::NewExternalArray(int length,
ExternalArrayType array_type,
void* external_pointer,
}
-Handle<Map> Factory::GetPixelArrayElementsMap(Handle<Map> src) {
- CALL_HEAP_FUNCTION(src->GetPixelArrayElementsMap(), Map);
+Handle<Map> Factory::NewExternalArrayElementsMap(Handle<Map> src) {
+ CALL_HEAP_FUNCTION(src->NewExternalArrayElementsMap(), Map);
}
static Handle<ByteArray> NewByteArray(int length,
PretenureFlag pretenure = NOT_TENURED);
- static Handle<PixelArray> NewPixelArray(
- int length,
- uint8_t* external_pointer,
- PretenureFlag pretenure = NOT_TENURED);
-
static Handle<ExternalArray> NewExternalArray(
int length,
ExternalArrayType array_type,
static Handle<Map> GetSlowElementsMap(Handle<Map> map);
- static Handle<Map> GetPixelArrayElementsMap(Handle<Map> map);
+ static Handle<Map> NewExternalArrayElementsMap(Handle<Map> map);
static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode) {
- if (object->HasPixelElements() || object->HasExternalArrayElements()) {
+ if (object->HasExternalArrayElements()) {
if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
bool has_exception;
Handle<Object> number = Execution::ToNumber(value, &has_exception);
uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode) {
- ASSERT(!object->HasPixelElements());
ASSERT(!object->HasExternalArrayElements());
CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode, false),
Object);
set_empty_byte_array(ByteArray::cast(obj));
{ MaybeObject* maybe_obj =
- AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize);
+ AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
- set_pixel_array_map(Map::cast(obj));
+ set_external_pixel_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
ExternalArray::kAlignedSize);
return kExternalUnsignedIntArrayMapRootIndex;
case kExternalFloatArray:
return kExternalFloatArrayMapRootIndex;
+ case kExternalPixelArray:
+ return kExternalPixelArrayMapRootIndex;
default:
UNREACHABLE();
return kUndefinedValueRootIndex;
}
-MaybeObject* Heap::AllocatePixelArray(int length,
- uint8_t* external_pointer,
- PretenureFlag pretenure) {
- AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
- Object* result;
- { MaybeObject* maybe_result =
- AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
-
- reinterpret_cast<PixelArray*>(result)->set_map(pixel_array_map());
- reinterpret_cast<PixelArray*>(result)->set_length(length);
- reinterpret_cast<PixelArray*>(result)->set_external_pointer(external_pointer);
-
- return result;
-}
-
-
MaybeObject* Heap::AllocateExternalArray(int length,
ExternalArrayType array_type,
void* external_pointer,
V(Map, external_ascii_string_map, ExternalAsciiStringMap) \
V(Map, undetectable_string_map, UndetectableStringMap) \
V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap) \
- V(Map, pixel_array_map, PixelArrayMap) \
+ V(Map, external_pixel_array_map, ExternalPixelArrayMap) \
V(Map, external_byte_array_map, ExternalByteArrayMap) \
V(Map, external_unsigned_byte_array_map, ExternalUnsignedByteArrayMap) \
V(Map, external_short_array_map, ExternalShortArrayMap) \
V(InitializeConstGlobal_symbol, "InitializeConstGlobal") \
V(KeyedLoadSpecialized_symbol, "KeyedLoadSpecialized") \
V(KeyedStoreSpecialized_symbol, "KeyedStoreSpecialized") \
- V(KeyedLoadPixelArray_symbol, "KeyedLoadPixelArray") \
- V(KeyedStorePixelArray_symbol, "KeyedStorePixelArray") \
V(stack_overflow_symbol, "kStackOverflowBoilerplate") \
V(illegal_access_symbol, "illegal access") \
V(out_of_memory_symbol, "out-of-memory") \
V(identity_hash_symbol, "v8::IdentityHash") \
V(closure_symbol, "(closure)") \
V(use_strict, "use strict") \
- V(KeyedLoadExternalArray_symbol, "KeyedLoadExternalArray") \
- V(KeyedStoreExternalArray_symbol, "KeyedStoreExternalArray")
+ V(KeyedLoadExternalByteArray_symbol, "KeyedLoadExternalByteArray") \
+ V(KeyedLoadExternalUnsignedByteArray_symbol, \
+ "KeyedLoadExternalUnsignedByteArray") \
+ V(KeyedLoadExternalShortArray_symbol, \
+ "KeyedLoadExternalShortArray") \
+ V(KeyedLoadExternalUnsignedShortArray_symbol, \
+ "KeyedLoadExternalUnsignedShortArray") \
+ V(KeyedLoadExternalIntArray_symbol, "KeyedLoadExternalIntArray") \
+ V(KeyedLoadExternalUnsignedIntArray_symbol, \
+ "KeyedLoadExternalUnsignedIntArray") \
+ V(KeyedLoadExternalFloatArray_symbol, "KeyedLoadExternalFloatArray") \
+ V(KeyedLoadExternalPixelArray_symbol, "KeyedLoadExternalPixelArray") \
+ V(KeyedStoreExternalByteArray_symbol, "KeyedStoreExternalByteArray") \
+ V(KeyedStoreExternalUnsignedByteArray_symbol, \
+ "KeyedStoreExternalUnsignedByteArray") \
+ V(KeyedStoreExternalShortArray_symbol, "KeyedStoreExternalShortArray") \
+ V(KeyedStoreExternalUnsignedShortArray_symbol, \
+ "KeyedStoreExternalUnsignedShortArray") \
+ V(KeyedStoreExternalIntArray_symbol, "KeyedStoreExternalIntArray") \
+ V(KeyedStoreExternalUnsignedIntArray_symbol, \
+ "KeyedStoreExternalUnsignedIntArray") \
+ V(KeyedStoreExternalFloatArray_symbol, "KeyedStoreExternalFloatArray") \
+ V(KeyedStoreExternalPixelArray_symbol, "KeyedStoreExternalPixelArray")
// Forward declarations.
class GCTracer;
// Please note this does not perform a garbage collection.
MUST_USE_RESULT static MaybeObject* AllocateByteArray(int length);
- // Allocate a pixel array of the specified length
- // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
- // failed.
- // Please note this does not perform a garbage collection.
- MUST_USE_RESULT static MaybeObject* AllocatePixelArray(int length,
- uint8_t* external_pointer,
- PretenureFlag pretenure);
-
// Allocates an external array of the specified length and type.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
V(CheckNonSmi) \
V(CheckPrototypeMaps) \
V(CheckSmi) \
+ V(ClassOfTest) \
V(Compare) \
V(CompareJSObjectEq) \
V(CompareMap) \
V(Deoptimize) \
V(Div) \
V(EnterInlined) \
+ V(ExternalArrayLength) \
V(FixedArrayLength) \
V(FunctionLiteral) \
V(GetCachedArrayIndex) \
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
+ V(HasInstanceType) \
+ V(HasCachedArrayIndex) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
V(IsNull) \
V(IsObject) \
V(IsSmi) \
V(IsConstructCall) \
- V(HasInstanceType) \
- V(HasCachedArrayIndex) \
V(JSArrayLength) \
- V(ClassOfTest) \
V(LeaveInlined) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadExternalArrayPointer) \
V(LoadFunctionPrototype) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(LoadPixelArrayElement) \
- V(LoadPixelArrayExternalPointer) \
V(Mod) \
V(Mul) \
V(ObjectLiteral) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
- V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
};
-class HPixelArrayLength: public HUnaryOperation {
+class HExternalArrayLength: public HUnaryOperation {
public:
- explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
+ explicit HExternalArrayLength(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Integer32());
// The result of this instruction is idempotent as long as its inputs don't
// change. The length of a pixel array cannot change once set, so it's not
return Representation::Tagged();
}
- DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
+ DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external_array_length")
protected:
virtual bool DataEquals(HValue* other) { return true; }
};
-class HLoadPixelArrayExternalPointer: public HUnaryOperation {
+class HLoadExternalArrayPointer: public HUnaryOperation {
public:
- explicit HLoadPixelArrayExternalPointer(HValue* value)
+ explicit HLoadExternalArrayPointer(HValue* value)
: HUnaryOperation(value) {
set_representation(Representation::External());
// The result of this instruction is idempotent as long as its inputs don't
return Representation::Tagged();
}
- DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
- "load-pixel-array-external-pointer")
+ DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+ "load-external-array-pointer")
protected:
virtual bool DataEquals(HValue* other) { return true; }
if (expr->IsMonomorphic()) {
Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
- // An object has either fast elements or pixel array elements, but never
- // both. Pixel array maps that are assigned to pixel array elements are
- // always created with the fast elements flag cleared.
- if (receiver_type->has_pixel_array_elements()) {
- instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
+ // An object has either fast elements or external array elements, but
+ // never both. Pixel array maps that are assigned to pixel array elements
+ // are always created with the fast elements flag cleared.
+ if (receiver_type->has_external_array_elements()) {
+ if (expr->GetExternalArrayType() == kExternalPixelArray) {
+ instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
+ }
} else if (receiver_type->has_fast_elements()) {
instr = BuildStoreKeyedFastElement(object, key, value, expr);
}
AddInstruction(new HCheckNonSmi(object));
Handle<Map> map = expr->GetMonomorphicReceiverType();
ASSERT(!map->has_fast_elements());
- ASSERT(map->has_pixel_array_elements());
+ ASSERT(map->has_external_array_elements());
AddInstruction(new HCheckMap(object, map));
HLoadElements* elements = new HLoadElements(object);
AddInstruction(elements);
- HInstruction* length = new HPixelArrayLength(elements);
+ HInstruction* length = new HExternalArrayLength(elements);
AddInstruction(length);
AddInstruction(new HBoundsCheck(key, length));
- HLoadPixelArrayExternalPointer* external_elements =
- new HLoadPixelArrayExternalPointer(elements);
+ HLoadExternalArrayPointer* external_elements =
+ new HLoadExternalArrayPointer(elements);
AddInstruction(external_elements);
HLoadPixelArrayElement* pixel_array_value =
new HLoadPixelArrayElement(external_elements, key);
AddInstruction(new HCheckNonSmi(object));
Handle<Map> map = expr->GetMonomorphicReceiverType();
ASSERT(!map->has_fast_elements());
- ASSERT(map->has_pixel_array_elements());
+ ASSERT(map->has_external_array_elements());
AddInstruction(new HCheckMap(object, map));
HLoadElements* elements = new HLoadElements(object);
AddInstruction(elements);
- HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
+ HInstruction* length = AddInstruction(new HExternalArrayLength(elements));
AddInstruction(new HBoundsCheck(key, length));
- HLoadPixelArrayExternalPointer* external_elements =
- new HLoadPixelArrayExternalPointer(elements);
+ HLoadExternalArrayPointer* external_elements =
+ new HLoadExternalArrayPointer(elements);
AddInstruction(external_elements);
return new HStorePixelArrayElement(external_elements, key, val);
}
// An object has either fast elements or pixel array elements, but never
// both. Pixel array maps that are assigned to pixel array elements are
// always created with the fast elements flag cleared.
- if (receiver_type->has_pixel_array_elements()) {
- instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
+ if (receiver_type->has_external_array_elements()) {
+ if (expr->GetExternalArrayType() == kExternalPixelArray) {
+ instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
+ }
} else if (receiver_type->has_fast_elements()) {
instr = BuildLoadKeyedFastElement(obj, key, expr);
}
}
-// Loads a indexed element from a pixel array.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements,
- Register untagged_key,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range) {
- // Register use:
- // receiver - holds the receiver and is unchanged.
- // key - holds the key and is unchanged (must be a smi).
- // elements - is set to the the receiver's element if
- // the receiver doesn't have a pixel array or the
- // key is not a smi, otherwise it's the elements'
- // external pointer.
- // untagged_key - is set to the untagged key
-
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit check
- // to ensure the key is a smi must be added.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
- __ mov(untagged_key, key);
- __ SmiUntag(untagged_key);
-
- __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
- // By passing NULL as not_pixel_array, callers signal that they have already
- // verified that the receiver has pixel array elements.
- if (not_pixel_array != NULL) {
- __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
- } else {
- if (FLAG_debug_code) {
- // Map check should have already made sure that elements is a pixel array.
- __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
- Immediate(Factory::pixel_array_map()));
- __ Assert(equal, "Elements isn't a pixel array");
- }
- }
-
- // Key must be in range.
- __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
- __ j(above_equal, out_of_range); // unsigned check handles negative keys.
-
- // Perform the indexed load and tag the result as a smi.
- __ mov(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset));
- __ movzx_b(result, Operand(elements, untagged_key, times_1, 0));
- __ SmiTag(result);
- __ ret(0);
-}
-
-
-// Stores an indexed element into a pixel array, clamping the stored value.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register scratch1,
- bool load_elements_from_receiver,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range) {
- // Register use:
- // receiver - holds the receiver and is unchanged unless the
- // store succeeds.
- // key - holds the key (must be a smi) and is unchanged.
- // value - holds the value (must be a smi) and is unchanged.
- // elements - holds the element object of the receiver on entry if
- // load_elements_from_receiver is false, otherwise used
- // internally to store the pixel arrays elements and
- // external array pointer.
- //
- // receiver, key and value remain unmodified until it's guaranteed that the
- // store will succeed.
- Register external_pointer = elements;
- Register untagged_key = scratch1;
- Register untagged_value = receiver; // Only set once success guaranteed.
-
- // Fetch the receiver's elements if the caller hasn't already done so.
- if (load_elements_from_receiver) {
- __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
- }
-
- // By passing NULL as not_pixel_array, callers signal that they have already
- // verified that the receiver has pixel array elements.
- if (not_pixel_array != NULL) {
- __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
- } else {
- if (FLAG_debug_code) {
- // Map check should have already made sure that elements is a pixel array.
- __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
- Immediate(Factory::pixel_array_map()));
- __ Assert(equal, "Elements isn't a pixel array");
- }
- }
-
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit check
- // to ensure the key is a smi must be added.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
-
- // Key must be a smi and it must be in range.
- __ mov(untagged_key, key);
- __ SmiUntag(untagged_key);
- __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
- __ j(above_equal, out_of_range); // unsigned check handles negative keys.
-
- // Value must be a smi.
- __ JumpIfNotSmi(value, value_not_smi);
- __ mov(untagged_value, value);
- __ SmiUntag(untagged_value);
-
- { // Clamp the value to [0..255].
- NearLabel done;
- __ test(untagged_value, Immediate(0xFFFFFF00));
- __ j(zero, &done);
- __ setcc(negative, untagged_value); // 1 if negative, 0 if positive.
- __ dec_b(untagged_value); // 0 if negative, 255 if positive.
- __ bind(&done);
- }
-
- __ mov(external_pointer,
- FieldOperand(elements, PixelArray::kExternalPointerOffset));
- __ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
- __ ret(0); // Return value in eax.
-}
-
-
#undef __
} } // namespace v8::internal
#endif
};
-
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements,
- Register untagged_key,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If the value is not a smi, the generated
-// code will branch to value_not_smi. If the receiver doesn't have pixel array
-// elements, the generated code will branch to not_pixel_array, unless
-// not_pixel_array is NULL, in which case the caller must ensure that the
-// receiver has pixel array elements. If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register scratch1,
- bool load_elements_from_receiver,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range);
-
} } // namespace v8::internal
#endif // V8_IA32_CODE_STUBS_IA32_H_
// -- esp[0] : return address
// -----------------------------------
Label slow, check_string, index_smi, index_string, property_array_property;
- Label check_pixel_array, probe_dictionary, check_number_dictionary;
+ Label probe_dictionary, check_number_dictionary;
// Check that the key is a smi.
__ test(eax, Immediate(kSmiTagMask));
// now in ecx.
__ test_b(FieldOperand(ecx, Map::kBitField2Offset),
1 << Map::kHasFastElements);
- __ j(zero, &check_pixel_array, not_taken);
+ __ j(zero, &check_number_dictionary, not_taken);
GenerateFastArrayLoad(masm,
edx,
__ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
__ ret(0);
- __ bind(&check_pixel_array);
- GenerateFastPixelArrayLoad(masm,
- edx,
- eax,
- ecx,
- ebx,
- eax,
- &check_number_dictionary,
- NULL,
- &slow);
-
__ bind(&check_number_dictionary);
+ __ mov(ebx, eax);
+ __ SmiUntag(ebx);
+ __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+
// Check whether the elements is a number dictionary.
// edx: receiver
// ebx: untagged index
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label slow, fast, array, extra, check_pixel_array;
+ Label slow, fast, array, extra;
// Check that the object isn't a smi.
__ test(edx, Immediate(kSmiTagMask));
// ecx: key (a smi)
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
// Check that the object is in fast mode and writable.
- __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
+ __ CheckMap(edi, Factory::fixed_array_map(), &slow, true);
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
__ j(below, &fast, taken);
__ bind(&slow);
GenerateRuntimeSetProperty(masm, strict_mode);
- // Check whether the elements is a pixel array.
- __ bind(&check_pixel_array);
- // eax: value
- // ecx: key (a smi)
- // edx: receiver
- // edi: elements array
- GenerateFastPixelArrayStore(masm,
- edx,
- ecx,
- eax,
- edi,
- ebx,
- false,
- NULL,
- &slow,
- &slow,
- &slow);
-
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
// element to the array by writing to array[array.length].
// edx: receiver, a JSArray
// ecx: key, a smi.
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
+ __ CheckMap(edi, Factory::fixed_array_map(), &slow, true);
// Check the key against the length in the array, compute the
// address to store into and fall through to fast case.
// -----------------------------------
//
// This accepts as a receiver anything JSObject::SetElementsLength accepts
- // (currently anything except for external and pixel arrays which means
- // anything with elements of FixedArray type.), but currently is restricted
- // to JSArray.
+ // (currently anything except for external arrays which means anything with
+ // elements of FixedArray type.), but currently is restricted to JSArray.
// Value must be a number, but only smis are accepted as the most common case.
Label miss;
}
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->InputAt(0));
- __ mov(result, FieldOperand(array, PixelArray::kLengthOffset));
+ __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset));
}
Immediate(Factory::fixed_array_map()));
__ j(equal, &done);
__ cmp(FieldOperand(result, HeapObject::kMapOffset),
- Immediate(Factory::pixel_array_map()));
+ Immediate(Factory::external_pixel_array_map()));
__ j(equal, &done);
__ cmp(FieldOperand(result, HeapObject::kMapOffset),
Immediate(Factory::fixed_cow_array_map()));
}
-void LCodeGen::DoLoadPixelArrayExternalPointer(
- LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+ LLoadExternalArrayPointer* instr) {
Register result = ToRegister(instr->result());
Register input = ToRegister(instr->InputAt(0));
- __ mov(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+ __ mov(result, FieldOperand(input,
+ ExternalArray::kExternalPointerOffset));
}
}
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+ HExternalArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LPixelArrayLength(array));
+ return DefineAsRegister(new LExternalArrayLength(array));
}
}
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
- HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+ HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+ return DefineAsRegister(new LLoadExternalArrayPointer(input));
}
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(ExternalArrayLength) \
V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadExternalArrayPointer) \
V(LoadFunctionPrototype) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(LoadPixelArrayElement) \
- V(LoadPixelArrayExternalPointer) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
- V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
};
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LPixelArrayLength(LOperand* value) {
+ explicit LExternalArrayLength(LOperand* value) {
inputs_[0] = value;
}
- DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
- DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+ DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
};
};
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ explicit LLoadExternalArrayPointer(LOperand* object) {
inputs_[0] = object;
}
- DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
- "load-pixel-array-external-pointer")
+ DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+ "load-external-array-pointer")
};
}
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
- JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
-
- // Do the load.
- GenerateFastPixelArrayStore(masm(),
- edx,
- ecx,
- eax,
- edi,
- ebx,
- true,
- &miss,
- &miss,
- NULL,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object,
JSObject* last) {
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- eax : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
-
- GenerateFastPixelArrayLoad(masm(),
- edx,
- eax,
- ecx,
- ebx,
- eax,
- &miss,
- &miss,
- &miss);
-
- // Handle load cache miss.
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
// Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body.
MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) {
// ----------- S t a t e -------------
// -- eax : key
// -- edx : receiver
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &slow, not_taken);
- // Get the map of the receiver.
- __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
- // Check that the receiver does not require access checks. We need
- // to check this explicitly since this generic stub does not perform
- // map checks.
- __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
- 1 << Map::kIsAccessCheckNeeded);
- __ j(not_zero, &slow, not_taken);
-
- __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
- __ j(not_equal, &slow, not_taken);
-
- // Check that the elements array is the appropriate type of
- // ExternalArray.
+ // Check that the map matches.
+ __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
- Handle<Map> map(Heap::MapForExternalArrayType(array_type));
- __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
- Immediate(map));
- __ j(not_equal, &slow, not_taken);
// eax: key, known to be a smi.
// edx: receiver, known to be a JSObject.
__ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
// Unsigned comparison catches both negative and too-large values.
__ j(above_equal, &slow);
-
__ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
// ebx: base pointer of external storage
switch (array_type) {
case kExternalByteArray:
- __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
+ __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
break;
case kExternalUnsignedByteArray:
- __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
+ case kExternalPixelArray:
+ __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
break;
case kExternalShortArray:
- __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
+ __ movsx_w(eax, Operand(ebx, ecx, times_2, 0));
break;
case kExternalUnsignedShortArray:
- __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
+ __ movzx_w(eax, Operand(ebx, ecx, times_2, 0));
break;
case kExternalIntArray:
case kExternalUnsignedIntArray:
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
__ ret(0);
} else {
- __ mov(eax, ecx);
__ SmiTag(eax);
__ ret(0);
}
MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// Check that the object isn't a smi.
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &slow);
- // Get the map from the receiver.
- __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
- // Check that the receiver does not require access checks. We need
- // to do this because this generic stub does not perform map checks.
- __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
- 1 << Map::kIsAccessCheckNeeded);
- __ j(not_zero, &slow);
+
+ // Check that the map matches.
+ __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
+
// Check that the key is a smi.
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &slow);
- // Get the instance type from the map of the receiver.
- __ CmpInstanceType(edi, JS_OBJECT_TYPE);
- __ j(not_equal, &slow);
-
- // Check that the elements array is the appropriate type of
- // ExternalArray.
- // eax: value
- // edx: receiver, a JSObject
- // ecx: key, a smi
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
- &slow, true);
// Check that the index is in range.
+ __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
__ mov(ebx, ecx);
__ SmiUntag(ebx);
__ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
// edi: elements array
// ebx: untagged index
__ test(eax, Immediate(kSmiTagMask));
- __ j(not_equal, &check_heap_number);
+ if (array_type == kExternalPixelArray)
+ __ j(not_equal, &slow);
+ else
+ __ j(not_equal, &check_heap_number);
+
// smi case
__ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
__ SmiUntag(ecx);
__ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
// ecx: base pointer of external storage
switch (array_type) {
+ case kExternalPixelArray:
+ { // Clamp the value to [0..255].
+ NearLabel done;
+ __ test(ecx, Immediate(0xFFFFFF00));
+ __ j(zero, &done);
+ __ setcc(negative, ecx); // 1 if negative, 0 if positive.
+ __ dec_b(ecx); // 0 if negative, 255 if positive.
+ __ bind(&done);
+ }
+ __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+ break;
case kExternalByteArray:
case kExternalUnsignedByteArray:
__ mov_b(Operand(edi, ebx, times_1, 0), ecx);
}
__ ret(0); // Return the original value.
- __ bind(&check_heap_number);
- // eax: value
- // edx: receiver
- // ecx: key
- // edi: elements array
- // ebx: untagged index
- __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
- Immediate(Factory::heap_number_map()));
- __ j(not_equal, &slow);
-
- // The WebGL specification leaves the behavior of storing NaN and
- // +/-Infinity into integer arrays basically undefined. For more
- // reproducible behavior, convert these to zero.
- __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
- // ebx: untagged index
- // edi: base pointer of external storage
- if (array_type == kExternalFloatArray) {
- __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ fstp_s(Operand(edi, ebx, times_4, 0));
- __ ret(0);
- } else {
- // Perform float-to-int conversion with truncation (round-to-zero)
- // behavior.
-
- // For the moment we make the slow call to the runtime on
- // processors that don't support SSE2. The code in IntegerConvert
- // (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) {
- ASSERT(CpuFeatures::IsSupported(SSE2));
- CpuFeatures::Scope scope(SSE2);
- __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
- // ecx: untagged integer value
- switch (array_type) {
- case kExternalByteArray:
- case kExternalUnsignedByteArray:
- __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
- break;
- case kExternalShortArray:
- case kExternalUnsignedShortArray:
- __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
- break;
- default:
- UNREACHABLE();
- break;
- }
- } else {
- if (CpuFeatures::IsSupported(SSE3)) {
- CpuFeatures::Scope scope(SSE3);
- // fisttp stores values as signed integers. To represent the
- // entire range of int and unsigned int arrays, store as a
- // 64-bit int and discard the high 32 bits.
- // If the value is NaN or +/-infinity, the result is 0x80000000,
- // which is automatically zero when taken mod 2^n, n < 32.
- __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ sub(Operand(esp), Immediate(2 * kPointerSize));
- __ fisttp_d(Operand(esp, 0));
- __ pop(ecx);
- __ add(Operand(esp), Immediate(kPointerSize));
- } else {
+ // TODO(danno): handle heap number -> pixel array conversion
+ if (array_type != kExternalPixelArray) {
+ __ bind(&check_heap_number);
+ // eax: value
+ // edx: receiver
+ // ecx: key
+ // edi: elements array
+ // ebx: untagged index
+ __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
+ Immediate(Factory::heap_number_map()));
+ __ j(not_equal, &slow);
+
+ // The WebGL specification leaves the behavior of storing NaN and
+ // +/-Infinity into integer arrays basically undefined. For more
+ // reproducible behavior, convert these to zero.
+ __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
+ // ebx: untagged index
+ // edi: base pointer of external storage
+ if (array_type == kExternalFloatArray) {
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ fstp_s(Operand(edi, ebx, times_4, 0));
+ __ ret(0);
+ } else {
+ // Perform float-to-int conversion with truncation (round-to-zero)
+ // behavior.
+
+ // For the moment we make the slow call to the runtime on
+ // processors that don't support SSE2. The code in IntegerConvert
+ // (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) {
ASSERT(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope scope(SSE2);
- // We can easily implement the correct rounding behavior for the
- // range [0, 2^31-1]. For the time being, to keep this code simple,
- // make the slow runtime call for values outside this range.
- // Note: we could do better for signed int arrays.
- __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
- // We will need the key if we have to make the slow runtime call.
- __ push(ecx);
- __ LoadPowerOf2(xmm1, ecx, 31);
- __ pop(ecx);
- __ ucomisd(xmm1, xmm0);
- __ j(above_equal, &slow);
- __ cvttsd2si(ecx, Operand(xmm0));
+ __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
+ // ecx: untagged integer value
+ switch (array_type) {
+ case kExternalPixelArray:
+ { // Clamp the value to [0..255].
+ NearLabel done;
+ __ test(ecx, Immediate(0xFFFFFF00));
+ __ j(zero, &done);
+ __ setcc(negative, ecx); // 1 if negative, 0 if positive.
+ __ dec_b(ecx); // 0 if negative, 255 if positive.
+ __ bind(&done);
+ }
+ __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+ case kExternalByteArray:
+ case kExternalUnsignedByteArray:
+ __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+ break;
+ case kExternalShortArray:
+ case kExternalUnsignedShortArray:
+ __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } else {
+ if (CpuFeatures::IsSupported(SSE3)) {
+ CpuFeatures::Scope scope(SSE3);
+ // fisttp stores values as signed integers. To represent the
+ // entire range of int and unsigned int arrays, store as a
+ // 64-bit int and discard the high 32 bits.
+ // If the value is NaN or +/-infinity, the result is 0x80000000,
+ // which is automatically zero when taken mod 2^n, n < 32.
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ sub(Operand(esp), Immediate(2 * kPointerSize));
+ __ fisttp_d(Operand(esp, 0));
+ __ pop(ecx);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ } else {
+ ASSERT(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope scope(SSE2);
+ // We can easily implement the correct rounding behavior for the
+ // range [0, 2^31-1]. For the time being, to keep this code simple,
+ // make the slow runtime call for values outside this range.
+ // Note: we could do better for signed int arrays.
+ __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
+ // We will need the key if we have to make the slow runtime call.
+ __ push(ecx);
+ __ LoadPowerOf2(xmm1, ecx, 31);
+ __ pop(ecx);
+ __ ucomisd(xmm1, xmm0);
+ __ j(above_equal, &slow);
+ __ cvttsd2si(ecx, Operand(xmm0));
+ }
+ // ecx: untagged integer value
+ __ mov(Operand(edi, ebx, times_4, 0), ecx);
}
- // ecx: untagged integer value
- __ mov(Operand(edi, ebx, times_4, 0), ecx);
+ __ ret(0); // Return original value.
}
- __ ret(0); // Return original value.
}
}
switch (target->kind()) {
case Code::LOAD_IC: return LoadIC::Clear(address, target);
- case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
+ case Code::KEYED_LOAD_IC:
+ case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
+ return KeyedLoadIC::Clear(address, target);
case Code::STORE_IC: return StoreIC::Clear(address, target);
- case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
+ case Code::KEYED_STORE_IC:
+ case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
+ return KeyedStoreIC::Clear(address, target);
case Code::CALL_IC: return CallIC::Clear(address, target);
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
case Code::BINARY_OP_IC:
NULL : Code::cast(probe->ToObjectUnchecked());
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
- } else if (receiver->HasPixelElements()) {
- MaybeObject* probe =
- StubCache::ComputeKeyedLoadPixelArray(*receiver);
- stub = probe->IsFailure() ?
- NULL : Code::cast(probe->ToObjectUnchecked());
} else if (key->IsSmi() &&
receiver->map()->has_fast_elements()) {
MaybeObject* probe =
*receiver, true, strict_mode);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
- } else if (receiver->HasPixelElements()) {
- MaybeObject* probe =
- StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
- stub = probe->IsFailure() ?
- NULL : Code::cast(probe->ToObjectUnchecked());
} else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
MaybeObject* probe =
StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
description = "A keyed load IC from the snapshot";
tag = Logger::KEYED_LOAD_IC_TAG;
break;
+ case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
+ description = "A keyed external array load IC from the snapshot";
+ tag = Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG;
+ break;
case Code::LOAD_IC:
description = "A load IC from the snapshot";
tag = Logger::LOAD_IC_TAG;
description = "A keyed store IC from the snapshot";
tag = Logger::KEYED_STORE_IC_TAG;
break;
+ case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
+ description = "A keyed external array store IC from the snapshot";
+ tag = Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG;
+ break;
case Code::CALL_IC:
description = "A call IC from the snapshot";
tag = Logger::CALL_IC_TAG;
V(EVAL_TAG, "Eval") \
V(FUNCTION_TAG, "Function") \
V(KEYED_LOAD_IC_TAG, "KeyedLoadIC") \
+ V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC") \
V(KEYED_STORE_IC_TAG, "KeyedStoreIC") \
+ V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")\
V(LAZY_COMPILE_TAG, "LazyCompile") \
V(LOAD_IC_TAG, "LoadIC") \
V(REG_EXP_TAG, "RegExp") \
case BYTE_ARRAY_TYPE:
ByteArray::cast(this)->ByteArrayVerify();
break;
- case PIXEL_ARRAY_TYPE:
- PixelArray::cast(this)->PixelArrayVerify();
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
+ ExternalPixelArray::cast(this)->ExternalPixelArrayVerify();
break;
case EXTERNAL_BYTE_ARRAY_TYPE:
ExternalByteArray::cast(this)->ExternalByteArrayVerify();
}
-void PixelArray::PixelArrayVerify() {
- ASSERT(IsPixelArray());
+void ExternalPixelArray::ExternalPixelArrayVerify() {
+ ASSERT(IsExternalPixelArray());
}
MapVerify();
ASSERT(is_shared());
ASSERT_EQ(Heap::empty_descriptor_array(), instance_descriptors());
- ASSERT_EQ(Heap::empty_fixed_array(), code_cache());
ASSERT_EQ(0, pre_allocated_property_fields());
ASSERT_EQ(0, unused_property_fields());
ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
info->number_of_fast_unused_elements_ += holes;
break;
}
- case PIXEL_ELEMENTS: {
+ case EXTERNAL_PIXEL_ELEMENTS: {
info->number_of_objects_with_fast_elements_++;
- PixelArray* e = PixelArray::cast(elements());
+ ExternalPixelArray* e = ExternalPixelArray::cast(elements());
info->number_of_fast_used_elements_ += e->length();
break;
}
}
-bool Object::IsPixelArray() {
+bool Object::IsExternalPixelArray() {
return Object::IsHeapObject() &&
- HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
+ HeapObject::cast(this)->map()->instance_type() ==
+ EXTERNAL_PIXEL_ARRAY_TYPE;
}
HeapObject* JSObject::elements() {
Object* array = READ_FIELD(this, kElementsOffset);
// In the assert below Dictionary is covered under FixedArray.
- ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
- array->IsExternalArray());
+ ASSERT(array->IsFixedArray() || array->IsExternalArray());
return reinterpret_cast<HeapObject*>(array);
}
(value->map() == Heap::fixed_array_map() ||
value->map() == Heap::fixed_cow_array_map()));
// In the assert below Dictionary is covered under FixedArray.
- ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
- value->IsExternalArray());
+ ASSERT(value->IsFixedArray() || value->IsExternalArray());
WRITE_FIELD(this, kElementsOffset, value);
CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
}
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(Proxy)
CAST_ACCESSOR(ByteArray)
-CAST_ACCESSOR(PixelArray)
CAST_ACCESSOR(ExternalArray)
CAST_ACCESSOR(ExternalByteArray)
CAST_ACCESSOR(ExternalUnsignedByteArray)
CAST_ACCESSOR(ExternalIntArray)
CAST_ACCESSOR(ExternalUnsignedIntArray)
CAST_ACCESSOR(ExternalFloatArray)
+CAST_ACCESSOR(ExternalPixelArray)
CAST_ACCESSOR(Struct)
SMI_ACCESSORS(FixedArray, length, kLengthOffset)
SMI_ACCESSORS(ByteArray, length, kLengthOffset)
-INT_ACCESSORS(PixelArray, length, kLengthOffset)
INT_ACCESSORS(ExternalArray, length, kLengthOffset)
}
-uint8_t* PixelArray::external_pointer() {
- intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
- return reinterpret_cast<uint8_t*>(ptr);
+uint8_t* ExternalPixelArray::external_pixel_pointer() {
+ return reinterpret_cast<uint8_t*>(external_pointer());
}
-void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
- intptr_t ptr = reinterpret_cast<intptr_t>(value);
- WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
-}
-
-
-uint8_t PixelArray::get(int index) {
+uint8_t ExternalPixelArray::get(int index) {
ASSERT((index >= 0) && (index < this->length()));
- uint8_t* ptr = external_pointer();
+ uint8_t* ptr = external_pixel_pointer();
return ptr[index];
}
-void PixelArray::set(int index, uint8_t value) {
+void ExternalPixelArray::set(int index, uint8_t value) {
ASSERT((index >= 0) && (index < this->length()));
- uint8_t* ptr = external_pointer();
+ uint8_t* ptr = external_pixel_pointer();
ptr[index] = value;
}
}
+ExternalArrayType Code::external_array_type() {
+ ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
+ byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset);
+ return static_cast<ExternalArrayType>(type);
+}
+
+
+void Code::set_external_array_type(ExternalArrayType value) {
+ ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
+ WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value);
+}
+
+
byte Code::binary_op_type() {
ASSERT(is_binary_op_stub());
return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
}
-MaybeObject* Map::GetPixelArrayElementsMap() {
- if (has_pixel_array_elements()) return this;
+MaybeObject* Map::NewExternalArrayElementsMap() {
// TODO(danno): Special case empty object map (or most common case)
// to return a pre-canned pixel array map.
Object* obj;
}
Map* new_map = Map::cast(obj);
new_map->set_has_fast_elements(false);
- new_map->set_has_pixel_array_elements(true);
- Counters::map_to_pixel_array_elements.Increment();
+ new_map->set_has_external_array_elements(true);
+ Counters::map_to_external_array_elements.Increment();
return new_map;
}
return EXTERNAL_INT_ELEMENTS;
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
return EXTERNAL_UNSIGNED_INT_ELEMENTS;
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
+ return EXTERNAL_PIXEL_ELEMENTS;
default:
- ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
- return EXTERNAL_FLOAT_ELEMENTS;
+ break;
}
}
- ASSERT(array->IsPixelArray());
- return PIXEL_ELEMENTS;
+ ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
+ return EXTERNAL_FLOAT_ELEMENTS;
}
}
-bool JSObject::HasPixelElements() {
- return GetElementsKind() == PIXEL_ELEMENTS;
-}
-
-
bool JSObject::HasExternalArrayElements() {
- return (HasExternalByteElements() ||
- HasExternalUnsignedByteElements() ||
- HasExternalShortElements() ||
- HasExternalUnsignedShortElements() ||
- HasExternalIntElements() ||
- HasExternalUnsignedIntElements() ||
- HasExternalFloatElements());
-}
-
-
-bool JSObject::HasExternalByteElements() {
- return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalUnsignedByteElements() {
- return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalShortElements() {
- return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalUnsignedShortElements() {
- return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalIntElements() {
- return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
+ HeapObject* array = elements();
+ ASSERT(array != NULL);
+ return array->IsExternalArray();
}
-bool JSObject::HasExternalUnsignedIntElements() {
- return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
+#define EXTERNAL_ELEMENTS_CHECK(name, type) \
+bool JSObject::HasExternal##name##Elements() { \
+ HeapObject* array = elements(); \
+ ASSERT(array != NULL); \
+ if (!array->IsHeapObject()) \
+ return false; \
+ return array->map()->instance_type() == type; \
}
-bool JSObject::HasExternalFloatElements() {
- return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
-}
+EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
+ EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
+ EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Float,
+ EXTERNAL_FLOAT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
bool JSObject::HasNamedInterceptor() {
bool JSObject::AllowsSetElementsLength() {
bool result = elements()->IsFixedArray();
- ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
+ ASSERT(result == !HasExternalArrayElements());
return result;
}
case BYTE_ARRAY_TYPE:
ByteArray::cast(this)->ByteArrayPrint(out);
break;
- case PIXEL_ARRAY_TYPE:
- PixelArray::cast(this)->PixelArrayPrint(out);
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
+ ExternalPixelArray::cast(this)->ExternalPixelArrayPrint(out);
break;
case EXTERNAL_BYTE_ARRAY_TYPE:
ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
}
-void PixelArray::PixelArrayPrint(FILE* out) {
- PrintF(out, "pixel array");
+void ExternalPixelArray::ExternalPixelArrayPrint(FILE* out) {
+ PrintF(out, "external pixel array");
}
}
break;
}
- case PIXEL_ELEMENTS: {
- PixelArray* p = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* p = ExternalPixelArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, p->get(i));
}
case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
- case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
+ case EXTERNAL_PIXEL_ARRAY_TYPE: return "EXTERNAL_PIXEL_ARRAY";
case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
return kVisitJSFunction;
case HEAP_NUMBER_TYPE:
- case PIXEL_ARRAY_TYPE:
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
case EXTERNAL_BYTE_ARRAY_TYPE:
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
case EXTERNAL_SHORT_ARRAY_TYPE:
case BYTE_ARRAY_TYPE:
accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
break;
- case PIXEL_ARRAY_TYPE:
- accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length());
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
+ accumulator->Add("<ExternalPixelArray[%u]>",
+ ExternalPixelArray::cast(this)->length());
break;
case EXTERNAL_BYTE_ARRAY_TYPE:
accumulator->Add("<ExternalByteArray[%u]>",
case HEAP_NUMBER_TYPE:
case FILLER_TYPE:
case BYTE_ARRAY_TYPE:
- case PIXEL_ARRAY_TYPE:
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
case EXTERNAL_BYTE_ARRAY_TYPE:
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
case EXTERNAL_SHORT_ARRAY_TYPE:
MaybeObject* JSObject::NormalizeElements() {
- ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+ ASSERT(!HasExternalArrayElements());
if (HasDictionaryElements()) return this;
ASSERT(map()->has_fast_elements());
MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index,
DeleteMode mode) {
- ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+ ASSERT(!HasExternalArrayElements());
switch (GetElementsKind()) {
case FAST_ELEMENTS: {
Object* obj;
}
break;
}
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
// Check if the object is among the indexed properties.
switch (GetElementsKind()) {
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
switch (GetElementsKind()) {
case FAST_ELEMENTS:
break;
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
switch (GetElementsKind()) {
case FAST_ELEMENTS:
break;
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
- ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements());
+ ASSERT(!array->HasExternalArrayElements());
switch (array->GetElementsKind()) {
case JSObject::FAST_ELEMENTS:
return UnionOfKeys(FixedArray::cast(array->elements()));
case BUILTIN: return "BUILTIN";
case LOAD_IC: return "LOAD_IC";
case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
+ case KEYED_EXTERNAL_ARRAY_LOAD_IC: return "KEYED_EXTERNAL_ARRAY_LOAD_IC";
case STORE_IC: return "STORE_IC";
case KEYED_STORE_IC: return "KEYED_STORE_IC";
+ case KEYED_EXTERNAL_ARRAY_STORE_IC: return "KEYED_EXTERNAL_ARRAY_STORE_IC";
case CALL_IC: return "CALL_IC";
case KEYED_CALL_IC: return "KEYED_CALL_IC";
case BINARY_OP_IC: return "BINARY_OP_IC";
MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
int length) {
// We should never end in here with a pixel or external array.
- ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+ ASSERT(!HasExternalArrayElements());
Object* obj;
{ MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity);
MaybeObject* JSObject::SetSlowElements(Object* len) {
// We should never end in here with a pixel or external array.
- ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+ ASSERT(!HasExternalArrayElements());
uint32_t new_length = static_cast<uint32_t>(len->Number());
}
break;
}
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
return true;
}
}
break;
}
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
break;
}
!FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
break;
}
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
return true;
}
case FAST_ELEMENTS:
// Fast case.
return SetFastElement(index, value, strict_mode, check_prototype);
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
return pixels->SetValue(index, value);
}
case EXTERNAL_BYTE_ELEMENTS: {
}
break;
}
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
}
break;
}
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
// Get element works for both JSObject and JSArray since
// JSArray::length cannot change.
switch (GetElementsKind()) {
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
uint8_t value = pixels->get(index);
return Smi::FromInt(value);
}
break;
}
- case PIXEL_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
}
- case PIXEL_ELEMENTS: {
- PixelArray* pixels = PixelArray::cast(elements());
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
return index < static_cast<uint32_t>(pixels->length());
}
case EXTERNAL_BYTE_ELEMENTS:
ASSERT(!storage || storage->length() >= counter);
break;
}
- case PIXEL_ELEMENTS: {
- int length = PixelArray::cast(elements())->length();
+ case EXTERNAL_PIXEL_ELEMENTS: {
+ int length = ExternalPixelArray::cast(elements())->length();
while (counter < length) {
if (storage != NULL) {
storage->set(counter, Smi::FromInt(counter));
// If the object is in dictionary mode, it is converted to fast elements
// mode.
MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
- ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+ ASSERT(!HasExternalArrayElements());
if (HasDictionaryElements()) {
// Convert to fast elements containing only the existing properties.
}
-Object* PixelArray::SetValue(uint32_t index, Object* value) {
+Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
uint8_t clamped_value = 0;
if (index < static_cast<uint32_t>(length())) {
if (value->IsSmi()) {
// - JSValue
// - JSMessageObject
// - ByteArray
-// - PixelArray
// - ExternalArray
+// - ExternalPixelArray
// - ExternalByteArray
// - ExternalUnsignedByteArray
// - ExternalShortArray
V(HEAP_NUMBER_TYPE) \
V(PROXY_TYPE) \
V(BYTE_ARRAY_TYPE) \
- V(PIXEL_ARRAY_TYPE) \
/* Note: the order of these external array */ \
/* types is relied upon in */ \
/* Object::IsExternalArray(). */ \
V(EXTERNAL_INT_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
+ V(EXTERNAL_PIXEL_ARRAY_TYPE) \
V(FILLER_TYPE) \
\
V(ACCESSOR_INFO_TYPE) \
HEAP_NUMBER_TYPE,
PROXY_TYPE,
BYTE_ARRAY_TYPE,
- PIXEL_ARRAY_TYPE,
EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
EXTERNAL_SHORT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
EXTERNAL_INT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
- EXTERNAL_FLOAT_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
+ EXTERNAL_FLOAT_ARRAY_TYPE,
+ EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
FILLER_TYPE, // LAST_DATA_TYPE
// Structs.
LAST_STRING_TYPE = FIRST_NONSTRING_TYPE - 1,
// Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
- LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_FLOAT_ARRAY_TYPE,
+ LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
// Boundary for promotion to old data space/old pointer space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundaries for testing the type is a JavaScript "object". Note that
V(SeqTwoByteString) \
V(SeqAsciiString) \
\
- V(PixelArray) \
V(ExternalArray) \
V(ExternalByteArray) \
V(ExternalUnsignedByteArray) \
V(ExternalIntArray) \
V(ExternalUnsignedIntArray) \
V(ExternalFloatArray) \
+ V(ExternalPixelArray) \
V(ByteArray) \
V(JSObject) \
V(JSContextExtensionObject) \
FAST_ELEMENTS,
// All the kinds below are "slow".
DICTIONARY_ELEMENTS,
- PIXEL_ELEMENTS,
EXTERNAL_BYTE_ELEMENTS,
EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
EXTERNAL_SHORT_ELEMENTS,
EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
EXTERNAL_INT_ELEMENTS,
EXTERNAL_UNSIGNED_INT_ELEMENTS,
- EXTERNAL_FLOAT_ELEMENTS
+ EXTERNAL_FLOAT_ELEMENTS,
+ EXTERNAL_PIXEL_ELEMENTS
};
// [properties]: Backing storage for properties.
// few objects and so before writing to any element the array must
// be copied. Use EnsureWritableFastElements in this case.
//
- // In the slow mode elements is either a NumberDictionary or a
- // PixelArray or an ExternalArray.
+ // In the slow mode elements is either a NumberDictionary or an ExternalArray.
DECL_ACCESSORS(elements, HeapObject)
inline void initialize_elements();
MUST_USE_RESULT inline MaybeObject* ResetElements();
inline ElementsKind GetElementsKind();
inline bool HasFastElements();
inline bool HasDictionaryElements();
- inline bool HasPixelElements();
+ inline bool HasExternalPixelElements();
inline bool HasExternalArrayElements();
inline bool HasExternalByteElements();
inline bool HasExternalUnsignedByteElements();
};
-// A PixelArray represents a fixed-size byte array with special semantics
-// used for implementing the CanvasPixelArray object. Please see the
-// specification at:
-// http://www.whatwg.org/specs/web-apps/current-work/
-// multipage/the-canvas-element.html#canvaspixelarray
-// In particular, write access clamps the value written to 0 or 255 if the
-// value written is outside this range.
-class PixelArray: public HeapObject {
- public:
- // [length]: length of the array.
- inline int length();
- inline void set_length(int value);
-
- // [external_pointer]: The pointer to the external memory area backing this
- // pixel array.
- DECL_ACCESSORS(external_pointer, uint8_t) // Pointer to the data store.
-
- // Setter and getter.
- inline uint8_t get(int index);
- inline void set(int index, uint8_t value);
-
- // This accessor applies the correct conversion from Smi, HeapNumber and
- // undefined and clamps the converted value between 0 and 255.
- Object* SetValue(uint32_t index, Object* value);
-
- // Casting.
- static inline PixelArray* cast(Object* obj);
-
-#ifdef OBJECT_PRINT
- inline void PixelArrayPrint() {
- PixelArrayPrint(stdout);
- }
- void PixelArrayPrint(FILE* out);
-#endif
-#ifdef DEBUG
- void PixelArrayVerify();
-#endif // DEBUG
-
- // Maximal acceptable length for a pixel array.
- static const int kMaxLength = 0x3fffffff;
-
- // PixelArray headers are not quadword aligned.
- static const int kLengthOffset = HeapObject::kHeaderSize;
- static const int kExternalPointerOffset =
- POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
- static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
- static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(PixelArray);
-};
-
-
// An ExternalArray represents a fixed-size array of primitive values
// which live outside the JavaScript heap. Its subclasses are used to
// implement the CanvasArray types being defined in the WebGL
};
+// A ExternalPixelArray represents a fixed-size byte array with special
+// semantics used for implementing the CanvasPixelArray object. Please see the
+// specification at:
+
+// http://www.whatwg.org/specs/web-apps/current-work/
+// multipage/the-canvas-element.html#canvaspixelarray
+// In particular, write access clamps the value written to 0 or 255 if the
+// value written is outside this range.
+class ExternalPixelArray: public ExternalArray {
+ public:
+ inline uint8_t* external_pixel_pointer();
+
+ // Setter and getter.
+ inline uint8_t get(int index);
+ inline void set(int index, uint8_t value);
+
+ // This accessor applies the correct conversion from Smi, HeapNumber and
+ // undefined and clamps the converted value between 0 and 255.
+ Object* SetValue(uint32_t index, Object* value);
+
+ // Casting.
+ static inline ExternalPixelArray* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+ inline void ExternalPixelArrayPrint() {
+ ExternalPixelArrayPrint(stdout);
+ }
+ void ExternalPixelArrayPrint(FILE* out);
+#endif
+#ifdef DEBUG
+ void ExternalPixelArrayVerify();
+#endif // DEBUG
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
+};
+
+
class ExternalByteArray: public ExternalArray {
public:
// Setter and getter.
BUILTIN,
LOAD_IC,
KEYED_LOAD_IC,
+ KEYED_EXTERNAL_ARRAY_LOAD_IC,
CALL_IC,
KEYED_CALL_IC,
STORE_IC,
KEYED_STORE_IC,
+ KEYED_EXTERNAL_ARRAY_STORE_IC,
BINARY_OP_IC,
TYPE_RECORDING_BINARY_OP_IC,
COMPARE_IC,
return kind() == TYPE_RECORDING_BINARY_OP_IC;
}
inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
+ inline bool is_external_array_load_stub() {
+ return kind() == KEYED_EXTERNAL_ARRAY_LOAD_IC;
+ }
+ inline bool is_external_array_store_stub() {
+ return kind() == KEYED_EXTERNAL_ARRAY_STORE_IC;
+ }
// [major_key]: For kind STUB or BINARY_OP_IC, the major key.
inline int major_key();
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);
+
// [binary op type]: For all BINARY_OP_IC.
inline byte binary_op_type();
inline void set_binary_op_type(byte value);
static const int kOptimizableOffset = kKindSpecificFlagsOffset;
static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
+ static const int kExternalArrayTypeOffset = kKindSpecificFlagsOffset;
static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
}
// Tells whether an instance has pixel array elements.
- inline void set_has_pixel_array_elements(bool value) {
+ inline void set_has_external_array_elements(bool value) {
if (value) {
- set_bit_field2(bit_field2() | (1 << kHasPixelArrayElements));
+ set_bit_field2(bit_field2() | (1 << kHasExternalArrayElements));
} else {
- set_bit_field2(bit_field2() & ~(1 << kHasPixelArrayElements));
+ set_bit_field2(bit_field2() & ~(1 << kHasExternalArrayElements));
}
}
- inline bool has_pixel_array_elements() {
- return ((1 << kHasPixelArrayElements) & bit_field2()) != 0;
+ inline bool has_external_array_elements() {
+ return ((1 << kHasExternalArrayElements) & bit_field2()) != 0;
}
// Tells whether the map is attached to SharedFunctionInfo
// from the descriptors and the fast elements bit cleared.
MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
- // Returns this map if it has the pixel array elements bit is set, otherwise
- // returns a copy of the map, with all transitions dropped from the
- // descriptors and the pixel array elements bit set.
- MUST_USE_RESULT inline MaybeObject* GetPixelArrayElementsMap();
+ // Returns a new map with all transitions dropped from the descriptors and the
+ // external array elements bit set.
+ MUST_USE_RESULT inline MaybeObject* NewExternalArrayElementsMap();
// Returns the property index for name (only valid for FAST MODE).
int PropertyIndexFor(String* name);
static const int kStringWrapperSafeForDefaultValueOf = 3;
static const int kAttachedToSharedFunctionInfo = 4;
static const int kIsShared = 5;
- static const int kHasPixelArrayElements = 6;
+ static const int kHasExternalArrayElements = 6;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
// Deep copy local elements.
// Pixel elements cannot be created using an object literal.
- ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
+ ASSERT(!copy->HasExternalArrayElements());
switch (copy->GetElementsKind()) {
case JSObject::FAST_ELEMENTS: {
FixedArray* elements = FixedArray::cast(copy->elements());
default: {
int dense_elements_length;
switch (kind) {
- case JSObject::PIXEL_ELEMENTS: {
+ case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
dense_elements_length =
- PixelArray::cast(object->elements())->length();
+ ExternalPixelArray::cast(object->elements())->length();
break;
}
case JSObject::EXTERNAL_BYTE_ELEMENTS: {
}
break;
}
- case JSObject::PIXEL_ELEMENTS: {
- Handle<PixelArray> pixels(PixelArray::cast(receiver->elements()));
+ case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
+ Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
+ receiver->elements()));
for (uint32_t j = 0; j < length; j++) {
Handle<Smi> e(Smi::FromInt(pixels->get(j)));
visitor->visit(j, e);
CASE(BUILTIN);
CASE(LOAD_IC);
CASE(KEYED_LOAD_IC);
+ CASE(KEYED_EXTERNAL_ARRAY_LOAD_IC);
CASE(STORE_IC);
CASE(KEYED_STORE_IC);
+ CASE(KEYED_EXTERNAL_ARRAY_STORE_IC);
CASE(CALL_IC);
CASE(KEYED_CALL_IC);
CASE(BINARY_OP_IC);
}
-MaybeObject* StubCache::ComputeKeyedLoadPixelArray(JSObject* receiver) {
- // Using NORMAL as the PropertyType for array element loads is a misuse. The
- // generated stub always accesses fast elements, not slow-mode fields, but
- // some property type is required for the stub lookup. Note that overloading
- // the NORMAL PropertyType is only safe as long as no stubs are generated for
- // other keyed field loads. This is guaranteed to be the case since all field
- // keyed loads that are not array elements go through a generic builtin stub.
- Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, NORMAL);
- String* name = Heap::KeyedLoadPixelArray_symbol();
- Object* code = receiver->map()->FindInCodeCache(name, flags);
- if (code->IsUndefined()) {
- KeyedLoadStubCompiler compiler;
- { MaybeObject* maybe_code = compiler.CompileLoadPixelArray(receiver);
- if (!maybe_code->ToObject(&code)) return maybe_code;
- }
- PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
- Object* result;
- { MaybeObject* maybe_result =
- receiver->UpdateMapCodeCache(name, Code::cast(code));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- }
- return code;
-}
-
-
MaybeObject* StubCache::ComputeStoreField(String* name,
JSObject* receiver,
int field_index,
}
-MaybeObject* StubCache::ComputeKeyedStorePixelArray(
- JSObject* receiver,
- StrictModeFlag strict_mode) {
- // Using NORMAL as the PropertyType for array element stores is a misuse. The
- // generated stub always accesses fast elements, not slow-mode fields, but
- // some property type is required for the stub lookup. Note that overloading
- // the NORMAL PropertyType is only safe as long as no stubs are generated for
- // other keyed field stores. This is guaranteed to be the case since all field
- // keyed stores that are not array elements go through a generic builtin stub.
- Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
- String* name = Heap::KeyedStorePixelArray_symbol();
- Object* code = receiver->map()->FindInCodeCache(name, flags);
- if (code->IsUndefined()) {
- KeyedStoreStubCompiler compiler(strict_mode);
- { MaybeObject* maybe_code = compiler.CompileStorePixelArray(receiver);
- if (!maybe_code->ToObject(&code)) return maybe_code;
- }
- PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
- Object* result;
- { MaybeObject* maybe_result =
- receiver->UpdateMapCodeCache(name, Code::cast(code));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- }
- return code;
-}
-
-
namespace {
ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
return kExternalUnsignedIntArray;
case JSObject::EXTERNAL_FLOAT_ELEMENTS:
return kExternalFloatArray;
+ case JSObject::EXTERNAL_PIXEL_ELEMENTS:
+ return kExternalPixelArray;
default:
UNREACHABLE();
return static_cast<ExternalArrayType>(0);
}
}
+String* ExternalArrayTypeToStubName(ExternalArrayType array_type,
+ bool is_store) {
+ if (is_store) {
+ switch (array_type) {
+ case kExternalByteArray:
+ return Heap::KeyedStoreExternalByteArray_symbol();
+ case kExternalUnsignedByteArray:
+ return Heap::KeyedStoreExternalUnsignedByteArray_symbol();
+ case kExternalShortArray:
+ return Heap::KeyedStoreExternalShortArray_symbol();
+ case kExternalUnsignedShortArray:
+ return Heap::KeyedStoreExternalUnsignedShortArray_symbol();
+ case kExternalIntArray:
+ return Heap::KeyedStoreExternalIntArray_symbol();
+ case kExternalUnsignedIntArray:
+ return Heap::KeyedStoreExternalUnsignedIntArray_symbol();
+ case kExternalFloatArray:
+ return Heap::KeyedStoreExternalFloatArray_symbol();
+ case kExternalPixelArray:
+ return Heap::KeyedStoreExternalPixelArray_symbol();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ } else {
+ switch (array_type) {
+ case kExternalByteArray:
+ return Heap::KeyedLoadExternalByteArray_symbol();
+ case kExternalUnsignedByteArray:
+ return Heap::KeyedLoadExternalUnsignedByteArray_symbol();
+ case kExternalShortArray:
+ return Heap::KeyedLoadExternalShortArray_symbol();
+ case kExternalUnsignedShortArray:
+ return Heap::KeyedLoadExternalUnsignedShortArray_symbol();
+ case kExternalIntArray:
+ return Heap::KeyedLoadExternalIntArray_symbol();
+ case kExternalUnsignedIntArray:
+ return Heap::KeyedLoadExternalUnsignedIntArray_symbol();
+ case kExternalFloatArray:
+ return Heap::KeyedLoadExternalFloatArray_symbol();
+ case kExternalPixelArray:
+ return Heap::KeyedLoadExternalPixelArray_symbol();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+}
+
} // anonymous namespace
StrictModeFlag strict_mode) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(
- is_store ? Code::KEYED_STORE_IC : Code::KEYED_LOAD_IC,
+ is_store ? Code::KEYED_EXTERNAL_ARRAY_STORE_IC :
+ Code::KEYED_EXTERNAL_ARRAY_LOAD_IC,
NORMAL,
strict_mode);
ExternalArrayType array_type =
ElementsKindToExternalArrayType(receiver->GetElementsKind());
- String* name =
- is_store ? Heap::KeyedStoreExternalArray_symbol()
- : Heap::KeyedLoadExternalArray_symbol();
- // Use the global maps for the particular external array types,
- // rather than the receiver's map, when looking up the cached code,
- // so that we actually canonicalize these stubs.
- Map* map = Heap::MapForExternalArrayType(array_type);
- Object* code = map->FindInCodeCache(name, flags);
+ String* name = ExternalArrayTypeToStubName(array_type, is_store);
+ Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
ExternalArrayStubCompiler compiler;
- { MaybeObject* maybe_code = is_store
- ? compiler.CompileKeyedStoreStub(array_type, flags)
- : compiler.CompileKeyedLoadStub(array_type, flags);
+ { MaybeObject* maybe_code =
+ is_store ?
+ compiler.CompileKeyedStoreStub(receiver, array_type, flags) :
+ compiler.CompileKeyedLoadStub(receiver, array_type, flags);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
+ Code::cast(code)->set_external_array_type(array_type);
if (is_store) {
PROFILE(
- CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
+ CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG,
+ Code::cast(code), 0));
} else {
PROFILE(
- CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
+ CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG,
+ Code::cast(code), 0));
}
Object* result;
{ MaybeObject* maybe_result =
- map->UpdateCodeCache(name, Code::cast(code));
+ receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadSpecialized(
JSObject* receiver);
- MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadPixelArray(
- JSObject* receiver);
-
// ---
MUST_USE_RESULT static MaybeObject* ComputeStoreField(
JSObject* receiver,
StrictModeFlag strict_mode);
- MUST_USE_RESULT static MaybeObject* ComputeKeyedStorePixelArray(
- JSObject* receiver,
- StrictModeFlag strict_mode);
-
MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
JSObject* receiver,
bool is_store,
MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
- MUST_USE_RESULT MaybeObject* CompileLoadPixelArray(JSObject* receiver);
private:
MaybeObject* GetCode(PropertyType type, String* name);
MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
- MUST_USE_RESULT MaybeObject* CompileStorePixelArray(JSObject* receiver);
-
private:
MaybeObject* GetCode(PropertyType type, String* name);
explicit ExternalArrayStubCompiler() {}
MUST_USE_RESULT MaybeObject* CompileKeyedLoadStub(
- ExternalArrayType array_type, Code::Flags flags);
+ JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
MUST_USE_RESULT MaybeObject* CompileKeyedStoreStub(
- ExternalArrayType array_type, Code::Flags flags);
+ JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
private:
MaybeObject* GetCode(Code::Flags flags);
bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
- return GetInfo(expr->position())->IsMap();
+ Handle<Object> map_or_code(GetInfo(expr->position()));
+ if (map_or_code->IsMap()) return true;
+ if (map_or_code->IsCode()) {
+ Handle<Code> code(Code::cast(*map_or_code));
+ return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC &&
+ code->FindFirstMap() != NULL;
+ }
+ return false;
}
-bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
- return GetInfo(expr->position())->IsMap();
+bool TypeFeedbackOracle::StoreIsMonomorphic(Assignment* expr) {
+ Handle<Object> map_or_code(GetInfo(expr->position()));
+ if (map_or_code->IsMap()) return true;
+ if (map_or_code->IsCode()) {
+ Handle<Code> code(Code::cast(*map_or_code));
+ return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC &&
+ code->FindFirstMap() != NULL;
+ }
+ return false;
}
Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
ASSERT(LoadIsMonomorphic(expr));
- return Handle<Map>::cast(GetInfo(expr->position()));
+ Handle<Object> map_or_code(
+ Handle<HeapObject>::cast(GetInfo(expr->position())));
+ if (map_or_code->IsCode()) {
+ Handle<Code> code(Code::cast(*map_or_code));
+ return Handle<Map>(code->FindFirstMap());
+ }
+ return Handle<Map>(Map::cast(*map_or_code));
}
Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
ASSERT(StoreIsMonomorphic(expr));
- return Handle<Map>::cast(GetInfo(expr->position()));
+ Handle<HeapObject> map_or_code(
+ Handle<HeapObject>::cast(GetInfo(expr->position())));
+ if (map_or_code->IsCode()) {
+ Handle<Code> code(Code::cast(*map_or_code));
+ return Handle<Map>(code->FindFirstMap());
+ }
+ return Handle<Map>(Map::cast(*map_or_code));
}
return check;
}
+ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType(
+ Property* expr) {
+ Handle<Object> stub = GetInfo(expr->position());
+ ASSERT(stub->IsCode());
+ return Code::cast(*stub)->external_array_type();
+}
+
+ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType(
+ Assignment* expr) {
+ Handle<Object> stub = GetInfo(expr->position());
+ ASSERT(stub->IsCode());
+ return Code::cast(*stub)->external_array_type();
+}
Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
CheckType check) {
value = target;
}
} else if (state == MONOMORPHIC) {
- if (target->kind() != Code::CALL_IC ||
- target->check_type() == RECEIVER_MAP_CHECK) {
+ if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC ||
+ kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) {
+ value = target;
+ } else if (kind != Code::CALL_IC ||
+ target->check_type() == RECEIVER_MAP_CHECK) {
Handle<Map> map = Handle<Map>(target->FindFirstMap());
if (*map == NULL) {
value = target;
ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
+ ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
+ ExternalArrayType GetKeyedStoreExternalArrayType(Assignment* expr);
+
CheckType GetCallCheckType(Call* expr);
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
SC(gc_last_resort_from_handles, V8.GCLastResortFromHandles) \
SC(map_slow_to_fast_elements, V8.MapSlowToFastElements) \
SC(map_fast_to_slow_elements, V8.MapFastToSlowElements) \
- SC(map_to_pixel_array_elements, V8.MapToPixelArrayElements) \
+ SC(map_to_external_array_elements, V8.MapToExternalArrayElements) \
/* How is the generic keyed-load stub used? */ \
SC(keyed_load_generic_smi, V8.KeyedLoadGenericSmi) \
SC(keyed_load_generic_symbol, V8.KeyedLoadGenericSymbol) \
}
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements,
- Register untagged_key,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range) {
- // Register use:
- // receiver - holds the receiver and is unchanged.
- // key - holds the key and is unchanged (must be a smi).
- // elements - is set to the the receiver's element if
- // the receiver doesn't have a pixel array or the
- // key is not a smi, otherwise it's the elements'
- // external pointer.
- // untagged_key - is set to the untagged key
-
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit check
- // to ensure the key is a smi must be added.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
- __ SmiToInteger32(untagged_key, key);
-
- __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
- // By passing NULL as not_pixel_array, callers signal that they have already
- // verified that the receiver has pixel array elements.
- if (not_pixel_array != NULL) {
- __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
- } else {
- if (FLAG_debug_code) {
- // Map check should have already made sure that elements is a pixel array.
- __ Cmp(FieldOperand(elements, HeapObject::kMapOffset),
- Factory::pixel_array_map());
- __ Assert(equal, "Elements isn't a pixel array");
- }
- }
-
- // Check that the smi is in range.
- __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
- __ j(above_equal, out_of_range); // unsigned check handles negative keys.
-
- // Load and tag the element as a smi.
- __ movq(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset));
- __ movzxbq(result, Operand(elements, untagged_key, times_1, 0));
- __ Integer32ToSmi(result, result);
- __ ret(0);
-}
-
-
-// Stores an indexed element into a pixel array, clamping the stored value.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register scratch1,
- bool load_elements_from_receiver,
- bool key_is_untagged,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range) {
- // Register use:
- // receiver - holds the receiver and is unchanged.
- // key - holds the key (must be a smi) and is unchanged.
- // value - holds the value (must be a smi) and is unchanged.
- // elements - holds the element object of the receiver on entry if
- // load_elements_from_receiver is false, otherwise used
- // internally to store the pixel arrays elements and
- // external array pointer.
- //
- Register external_pointer = elements;
- Register untagged_key = scratch1;
- Register untagged_value = receiver; // Only set once success guaranteed.
-
- // Fetch the receiver's elements if the caller hasn't already done so.
- if (load_elements_from_receiver) {
- __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
- }
-
- // By passing NULL as not_pixel_array, callers signal that they have already
- // verified that the receiver has pixel array elements.
- if (not_pixel_array != NULL) {
- __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
- } else {
- if (FLAG_debug_code) {
- // Map check should have already made sure that elements is a pixel array.
- __ Cmp(FieldOperand(elements, HeapObject::kMapOffset),
- Factory::pixel_array_map());
- __ Assert(equal, "Elements isn't a pixel array");
- }
- }
-
- // Key must be a smi and it must be in range.
- if (key_is_untagged) {
- untagged_key = key;
- } else {
- // Some callers already have verified that the key is a smi. key_not_smi is
- // set to NULL as a sentinel for that case. Otherwise, add an explicit
- // check to ensure the key is a smi.
- if (key_not_smi != NULL) {
- __ JumpIfNotSmi(key, key_not_smi);
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key);
- }
- }
- __ SmiToInteger32(untagged_key, key);
- }
- __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
- __ j(above_equal, out_of_range); // unsigned check handles negative keys.
-
- // Value must be a smi.
- __ JumpIfNotSmi(value, value_not_smi);
- __ SmiToInteger32(untagged_value, value);
-
- { // Clamp the value to [0..255].
- NearLabel done;
- __ testl(untagged_value, Immediate(0xFFFFFF00));
- __ j(zero, &done);
- __ setcc(negative, untagged_value); // 1 if negative, 0 if positive.
- __ decb(untagged_value); // 0 if negative, 255 if positive.
- __ bind(&done);
- }
-
- __ movq(external_pointer,
- FieldOperand(elements, PixelArray::kExternalPointerOffset));
- __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
- __ ret(0); // Return value in eax.
-}
-
#undef __
} } // namespace v8::internal
};
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register elements,
- Register untagged_key,
- Register result,
- Label* not_pixel_array,
- Label* key_not_smi,
- Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If the value is not a smi, the
-// generated code will branch to value_not_smi. If the receiver
-// doesn't have pixel array elements, the generated code will branch to
-// not_pixel_array, unless not_pixel_array is NULL, in which case the caller
-// must ensure that the receiver has pixel array elements. If key is not a
-// valid index within the bounds of the pixel array, the generated code jumps to
-// out_of_range.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register elements,
- Register scratch1,
- bool load_elements_from_receiver,
- bool key_is_untagged,
- Label* key_not_smi,
- Label* value_not_smi,
- Label* not_pixel_array,
- Label* out_of_range);
-
} } // namespace v8::internal
#endif // V8_X64_CODE_STUBS_X64_H_
// -- rsp[0] : return address
// -----------------------------------
Label slow, check_string, index_smi, index_string, property_array_property;
- Label check_pixel_array, probe_dictionary, check_number_dictionary;
+ Label probe_dictionary, check_number_dictionary;
// Check that the key is a smi.
__ JumpIfNotSmi(rax, &check_string);
// now in rcx.
__ testb(FieldOperand(rcx, Map::kBitField2Offset),
Immediate(1 << Map::kHasFastElements));
- __ j(zero, &check_pixel_array);
+ __ j(zero, &check_number_dictionary);
GenerateFastArrayLoad(masm,
rdx,
__ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
__ ret(0);
- __ bind(&check_pixel_array);
- GenerateFastPixelArrayLoad(masm,
- rdx,
- rax,
- rcx,
- rbx,
- rax,
- &check_number_dictionary,
- NULL,
- &slow);
-
__ bind(&check_number_dictionary);
+ __ SmiToInteger32(rbx, rax);
+ __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+
// Check whether the elements is a number dictionary.
// rdx: receiver
// rax: key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array;
+ Label slow, slow_with_tagged_index, fast, array, extra;
// Check that the object isn't a smi.
__ JumpIfSmi(rdx, &slow_with_tagged_index);
// Check that the object is in fast mode and writable.
__ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
Heap::kFixedArrayMapRootIndex);
- __ j(not_equal, &check_pixel_array);
+ __ j(not_equal, &slow);
__ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
// rax: value
// rbx: FixedArray
GenerateRuntimeSetProperty(masm, strict_mode);
// Never returns to here.
- // Check whether the elements is a pixel array.
- // rax: value
- // rdx: receiver
- // rbx: receiver's elements array
- // rcx: index, zero-extended.
- __ bind(&check_pixel_array);
- GenerateFastPixelArrayStore(masm,
- rdx,
- rcx,
- rax,
- rbx,
- rdi,
- false,
- true,
- NULL,
- &slow,
- &slow,
- &slow);
-
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
// element to the array by writing to array[array.length].
}
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->InputAt(0));
- __ movq(result, FieldOperand(array, PixelArray::kLengthOffset));
+ __ movq(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
}
Factory::fixed_array_map());
__ j(equal, &done);
__ Cmp(FieldOperand(result, HeapObject::kMapOffset),
- Factory::pixel_array_map());
+ Factory::external_pixel_array_map());
__ j(equal, &done);
__ Cmp(FieldOperand(result, HeapObject::kMapOffset),
Factory::fixed_cow_array_map());
}
-void LCodeGen::DoLoadPixelArrayExternalPointer(
- LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+ LLoadExternalArrayPointer* instr) {
Register result = ToRegister(instr->result());
Register input = ToRegister(instr->InputAt(0));
- __ movq(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+ __ movq(result, FieldOperand(input,
+ ExternalPixelArray::kExternalPointerOffset));
}
}
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+ HExternalArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LPixelArrayLength(array));
+ return DefineAsRegister(new LExternalArrayLength(array));
}
}
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
- HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+ HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+ return DefineAsRegister(new LLoadExternalArrayPointer(input));
}
V(CheckMap) \
V(CheckPrototypeMaps) \
V(CheckSmi) \
+ V(ClassOfTest) \
+ V(ClassOfTestAndBranch) \
V(CmpID) \
V(CmpIDAndBranch) \
V(CmpJSObjectEq) \
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(ExternalArrayLength) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(GetCachedArrayIndex) \
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
- V(FixedArrayLength) \
+ V(HasInstanceType) \
+ V(HasInstanceTypeAndBranch) \
+ V(HasCachedArrayIndex) \
+ V(HasCachedArrayIndexAndBranch) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
V(IsSmi) \
V(IsSmiAndBranch) \
V(JSArrayLength) \
- V(HasInstanceType) \
- V(HasInstanceTypeAndBranch) \
- V(HasCachedArrayIndex) \
- V(HasCachedArrayIndexAndBranch) \
- V(ClassOfTest) \
- V(ClassOfTestAndBranch) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadExternalArrayPointer) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadNamedGeneric) \
V(LoadFunctionPrototype) \
V(LoadPixelArrayElement) \
- V(LoadPixelArrayExternalPointer) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
- V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
};
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LPixelArrayLength(LOperand* value) {
+ explicit LExternalArrayLength(LOperand* value) {
inputs_[0] = value;
}
- DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
- DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+ DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
};
};
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
public:
- explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ explicit LLoadExternalArrayPointer(LOperand* object) {
inputs_[0] = object;
}
- DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
- "load-pixel-array-external-pointer")
+ DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+ "load-external-array-pointer")
};
}
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
- JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
-
- // Do the load.
- GenerateFastPixelArrayStore(masm(),
- rdx,
- rcx,
- rax,
- rdi,
- rbx,
- true,
- false,
- &miss,
- &miss,
- NULL,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object,
JSObject* last) {
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map matches.
- __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
-
- GenerateFastPixelArrayLoad(masm(),
- rdx,
- rax,
- rbx,
- rcx,
- rax,
- &miss,
- &miss,
- &miss);
-
- __ bind(&miss);
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
// Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body.
MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// Check that the key is a smi.
__ JumpIfNotSmi(rax, &slow);
- // Check that the object is a JS object.
- __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
- __ j(not_equal, &slow);
- // Check that the receiver does not require access checks. We need
- // to check this explicitly since this generic stub does not perform
- // map checks. The map is already in rdx.
- __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsAccessCheckNeeded));
- __ j(not_zero, &slow);
-
- // Check that the elements array is the appropriate type of
- // ExternalArray.
- // rax: index (as a smi)
- // rdx: JSObject
+ // Check that the map matches.
+ __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
__ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
- __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
- Heap::RootIndexForExternalArrayType(array_type));
- __ j(not_equal, &slow);
// Check that the index is in range.
__ SmiToInteger32(rcx, rax);
case kExternalByteArray:
__ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
break;
+ case kExternalPixelArray:
case kExternalUnsignedByteArray:
__ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
break;
MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
- ExternalArrayType array_type, Code::Flags flags) {
+ JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
// Check that the object isn't a smi.
__ JumpIfSmi(rdx, &slow);
- // Get the map from the receiver.
- __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
- // Check that the receiver does not require access checks. We need
- // to do this because this generic stub does not perform map checks.
- __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsAccessCheckNeeded));
- __ j(not_zero, &slow);
- // Check that the key is a smi.
- __ JumpIfNotSmi(rcx, &slow);
-
- // Check that the object is a JS object.
- __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
- __ j(not_equal, &slow);
- // Check that the elements array is the appropriate type of
- // ExternalArray.
- // rax: value
- // rcx: key (a smi)
- // rdx: receiver (a JSObject)
+ // Check that the map matches.
+ __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
__ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
- __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
- Heap::RootIndexForExternalArrayType(array_type));
- __ j(not_equal, &slow);
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(rcx, &slow);
// Check that the index is in range.
__ SmiToInteger32(rdi, rcx); // Untag the index.
// rbx: elements array
// rdi: untagged key
NearLabel check_heap_number;
- __ JumpIfNotSmi(rax, &check_heap_number);
+ if (array_type == kExternalPixelArray) {
+ // Float to pixel conversion is only implemented in the runtime for now.
+ __ JumpIfNotSmi(rax, &slow);
+ } else {
+ __ JumpIfNotSmi(rax, &check_heap_number);
+ }
// No more branches to slow case on this path. Key and receiver not needed.
__ SmiToInteger32(rdx, rax);
__ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
// rbx: base pointer of external storage
switch (array_type) {
+ case kExternalPixelArray:
+ { // Clamp the value to [0..255].
+ NearLabel done;
+ __ testl(rdx, Immediate(0xFFFFFF00));
+ __ j(zero, &done);
+ __ setcc(negative, rdx); // 1 if negative, 0 if positive.
+ __ decb(rdx); // 0 if negative, 255 if positive.
+ __ bind(&done);
+ }
+ __ movb(Operand(rbx, rdi, times_1, 0), rdx);
+ break;
case kExternalByteArray:
case kExternalUnsignedByteArray:
__ movb(Operand(rbx, rdi, times_1, 0), rdx);
}
__ ret(0);
- __ bind(&check_heap_number);
- // rax: value
- // rcx: key (a smi)
- // rdx: receiver (a JSObject)
- // rbx: elements array
- // rdi: untagged key
- __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
- __ j(not_equal, &slow);
- // No more branches to slow case on this path.
-
- // The WebGL specification leaves the behavior of storing NaN and
- // +/-Infinity into integer arrays basically undefined. For more
- // reproducible behavior, convert these to zero.
- __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
- __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
- // rdi: untagged index
- // rbx: base pointer of external storage
- // top of FPU stack: value
- if (array_type == kExternalFloatArray) {
- __ cvtsd2ss(xmm0, xmm0);
- __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
- __ ret(0);
- } else {
- // Perform float-to-int conversion with truncation (round-to-zero)
- // behavior.
-
- // Convert to int32 and store the low byte/word.
- // If the value is NaN or +/-infinity, the result is 0x80000000,
- // which is automatically zero when taken mod 2^n, n < 32.
- // rdx: value (converted to an untagged integer)
+ // TODO(danno): handle heap number -> pixel array conversion
+ if (array_type != kExternalPixelArray) {
+ __ bind(&check_heap_number);
+ // rax: value
+ // rcx: key (a smi)
+ // rdx: receiver (a JSObject)
+ // rbx: elements array
+ // rdi: untagged key
+ __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
+ __ j(not_equal, &slow);
+ // No more branches to slow case on this path.
+
+ // The WebGL specification leaves the behavior of storing NaN and
+ // +/-Infinity into integer arrays basically undefined. For more
+ // reproducible behavior, convert these to zero.
+ __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+ __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
// rdi: untagged index
// rbx: base pointer of external storage
- switch (array_type) {
- case kExternalByteArray:
- case kExternalUnsignedByteArray:
- __ cvttsd2si(rdx, xmm0);
- __ movb(Operand(rbx, rdi, times_1, 0), rdx);
- break;
- case kExternalShortArray:
- case kExternalUnsignedShortArray:
- __ cvttsd2si(rdx, xmm0);
- __ movw(Operand(rbx, rdi, times_2, 0), rdx);
- break;
- case kExternalIntArray:
- case kExternalUnsignedIntArray: {
- // 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;
+ // top of FPU stack: value
+ if (array_type == kExternalFloatArray) {
+ __ cvtsd2ss(xmm0, xmm0);
+ __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
+ __ ret(0);
+ } else {
+ // Perform float-to-int conversion with truncation (round-to-zero)
+ // behavior.
+
+ // Convert to int32 and store the low byte/word.
+ // If the value is NaN or +/-infinity, the result is 0x80000000,
+ // which is automatically zero when taken mod 2^n, n < 32.
+ // rdx: value (converted to an untagged integer)
+ // rdi: untagged index
+ // rbx: base pointer of external storage
+ switch (array_type) {
+ case kExternalByteArray:
+ case kExternalUnsignedByteArray:
+ __ cvttsd2si(rdx, xmm0);
+ __ movb(Operand(rbx, rdi, times_1, 0), rdx);
+ break;
+ case kExternalShortArray:
+ case kExternalUnsignedShortArray:
+ __ cvttsd2si(rdx, xmm0);
+ __ movw(Operand(rbx, rdi, times_2, 0), rdx);
+ break;
+ case kExternalIntArray:
+ case kExternalUnsignedIntArray: {
+ // 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:
+ UNREACHABLE();
+ break;
}
- default:
- UNREACHABLE();
- break;
+ __ ret(0);
}
- __ ret(0);
}
// Slow case: call runtime.
LocalContext context;
const int kElementCount = 260;
uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
- i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
- pixel_data);
+ i::Handle<i::ExternalPixelArray> pixels =
+ i::Handle<i::ExternalPixelArray>::cast(
+ i::Factory::NewExternalArray(kElementCount,
+ v8::kExternalPixelArray,
+ pixel_data));
i::Heap::CollectAllGarbage(false); // Force GC to trigger verification.
for (int i = 0; i < kElementCount; i++) {
pixels->set(i, i % 256);
" return sum; "
"}"
"for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
- "for (var i = 0; i < 10000; ++i) {"
+ "for (var i = 0; i < 5000; ++i) {"
" result = pa_load(pixels);"
"}"
"result");
" }"
" return sum; "
"}"
- "for (var i = 0; i < 100000; ++i) {"
+ "for (var i = 0; i < 5000; ++i) {"
" pa_init(pixels);"
"}"
"result = pa_load(pixels);"
LocalContext context;
const int kElementCount = 260;
uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
- i::Handle<i::PixelArray> pixels =
- i::Factory::NewPixelArray(kElementCount, pixel_data);
+ i::Handle<i::ExternalPixelArray> pixels =
+ i::Handle<i::ExternalPixelArray>::cast(
+ i::Factory::NewExternalArray(kElementCount,
+ v8::kExternalPixelArray,
+ pixel_data));
for (int i = 0; i < kElementCount; i++) {
pixels->set(i, i % 256);
}
switch (array_type) {
case v8::kExternalByteArray:
case v8::kExternalUnsignedByteArray:
+ case v8::kExternalPixelArray:
return 1;
break;
case v8::kExternalShortArray:
" ext_array[i] = Infinity;"
"}"
"ext_array[5];");
- CHECK_EQ(0, result->Int32Value());
- CHECK_EQ(0,
+ int expected_value =
+ (array_type == v8::kExternalPixelArray) ? 255 : 0;
+ CHECK_EQ(expected_value, result->Int32Value());
+ CHECK_EQ(expected_value,
i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {"
const char* signed_data =
"var source_data = [0.6, 10.6, -0.6, -10.6];"
"var expected_results = [0, 10, 0, -10];";
+ const char* pixel_data =
+ "var source_data = [0.6, 10.6];"
+ "var expected_results = [1, 11];";
bool is_unsigned =
(array_type == v8::kExternalUnsignedByteArray ||
array_type == v8::kExternalUnsignedShortArray ||
array_type == v8::kExternalUnsignedIntArray);
+ bool is_pixel_data = array_type == v8::kExternalPixelArray;
i::OS::SNPrintF(test_buf,
"%s"
" (ext_array[5] == expected_results[i]);"
"}"
"all_passed;",
- (is_unsigned ? unsigned_data : signed_data));
+ (is_unsigned ?
+ unsigned_data :
+ (is_pixel_data ? pixel_data : signed_data)));
result = CompileRun(test_buf.start());
CHECK_EQ(true, result->BooleanValue());
}
}
+THREADED_TEST(ExternalPixelArray) {
+ ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
+ v8::kExternalPixelArray,
+ 0,
+ 255);
+}
+
+
THREADED_TEST(ExternalShortArray) {
ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
v8::kExternalShortArray,
ExternalArrayInfoTestHelper(v8::kExternalIntArray);
ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
+ ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
}