return;
}
i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
- i::Handle<i::Map> slow_map =
- i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
- self->set_map(*slow_map);
+ 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);
}
}
+LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LPixelArrayLength(array));
+}
+
+
LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
return DefineAsRegister(new LFixedArrayLength(array));
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineSameAsFirst(new LLoadElements(input));
+ return DefineAsRegister(new LLoadElements(input));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
+ HLoadPixelArrayExternalPointer* instr) {
+ LOperand* input = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
}
}
+LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
+ HLoadPixelArrayElement* instr) {
+ ASSERT(instr->representation().IsInteger32());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* external_pointer =
+ UseRegisterAtStart(instr->external_pointer());
+ LOperand* key = UseRegisterAtStart(instr->key());
+ LLoadPixelArrayElement* result =
+ new LLoadPixelArrayElement(external_pointer, key);
+ return DefineAsRegister(result);
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), r1);
LOperand* key = UseFixed(instr->key(), r0);
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadPixelArrayElement) \
+ V(LoadPixelArrayExternalPointer) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
+ V(PixelArrayLength) \
V(PushArgument) \
V(RegExpLiteral) \
V(Return) \
};
+class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LPixelArrayLength(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+};
+
+
class LFixedArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayLength(LOperand* value) {
};
+class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
+ "load-pixel-array-external-pointer")
+};
+
+
class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
};
+class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+ inputs_[0] = external_pointer;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
+ "load-pixel-array-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+
+ LOperand* external_pointer() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
}
+void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->InputAt(0));
+ __ ldr(result, FieldMemOperand(array, PixelArray::kLengthOffset));
+}
+
+
void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->InputAt(0));
void LCodeGen::DoLoadElements(LLoadElements* instr) {
- ASSERT(instr->result()->Equals(instr->InputAt(0)));
- Register reg = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
+ Register input = ToRegister(instr->InputAt(0));
Register scratch = scratch0();
- __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset));
+ __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset));
if (FLAG_debug_code) {
Label done;
- __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
__ cmp(scratch, ip);
__ b(eq, &done);
+ __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+ __ cmp(scratch, ip);
+ __ b(eq, &done);
__ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
__ cmp(scratch, ip);
__ Check(eq, "Check for fast elements failed.");
}
+void LCodeGen::DoLoadPixelArrayExternalPointer(
+ LLoadPixelArrayExternalPointer* instr) {
+ Register to_reg = ToRegister(instr->result());
+ Register from_reg = ToRegister(instr->InputAt(0));
+ __ ldr(to_reg, FieldMemOperand(from_reg, PixelArray::kExternalPointerOffset));
+}
+
+
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
Register arguments = ToRegister(instr->arguments());
Register length = ToRegister(instr->length());
}
+void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
+ Register external_elements = ToRegister(instr->external_pointer());
+ Register key = ToRegister(instr->key());
+ Register result = ToRegister(instr->result());
+
+ // Load the result.
+ __ ldrb(result, MemOperand(external_elements, key));
+}
+
+
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(r1));
ASSERT(ToRegister(instr->key()).is(r0));
}
+Handle<Map> Factory::GetPixelArrayElementsMap(Handle<Map> src) {
+ CALL_HEAP_FUNCTION(src->GetPixelArrayElementsMap(), Map);
+}
+
+
Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
}
static Handle<Map> GetSlowElementsMap(Handle<Map> map);
+ static Handle<Map> GetPixelArrayElementsMap(Handle<Map> map);
+
static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
// Numbers (eg, literals) are pretenured by the parser.
}
+void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) const {
+ external_pointer()->PrintNameTo(stream);
+ stream->Add("[");
+ key()->PrintNameTo(stream);
+ stream->Add("]");
+}
+
+
void HStoreNamed::PrintDataTo(StringStream* stream) const {
object()->PrintNameTo(stream);
stream->Add(".");
V(LoadKeyedGeneric) \
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) \
V(InobjectFields) \
V(BackingStoreFields) \
V(ArrayElements) \
+ V(PixelArrayElements) \
V(GlobalVars) \
V(Maps) \
V(ArrayLengths) \
kTagged,
kDouble,
kInteger32,
+ kExternal,
kNumRepresentations
};
static Representation Tagged() { return Representation(kTagged); }
static Representation Integer32() { return Representation(kInteger32); }
static Representation Double() { return Representation(kDouble); }
+ static Representation External() { return Representation(kExternal); }
bool Equals(const Representation& other) const {
return kind_ == other.kind_;
bool IsTagged() const { return kind_ == kTagged; }
bool IsInteger32() const { return kind_ == kInteger32; }
bool IsDouble() const { return kind_ == kDouble; }
+ bool IsExternal() const { return kind_ == kExternal; }
bool IsSpecialization() const {
return kind_ == kInteger32 || kind_ == kDouble;
}
};
+class HPixelArrayLength: public HUnaryOperation {
+ public:
+ explicit HPixelArrayLength(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
+ // necessary to introduce a kDependsOnArrayLengths or any other dependency.
+ SetFlag(kUseGVN);
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
class HBitNot: public HUnaryOperation {
public:
explicit HBitNot(HValue* value) : HUnaryOperation(value) {
};
+class HLoadPixelArrayExternalPointer: public HUnaryOperation {
+ public:
+ explicit HLoadPixelArrayExternalPointer(HValue* value)
+ : HUnaryOperation(value) {
+ set_representation(Representation::External());
+ // The result of this instruction is idempotent as long as its inputs don't
+ // change. The external array of a pixel array elements object cannot
+ // change once set, so it's no necessary to introduce any additional
+ // dependencies on top of the inputs.
+ SetFlag(kUseGVN);
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
+ "load-pixel-array-external-pointer")
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
class HCheckMap: public HUnaryOperation {
public:
HCheckMap(HValue* value, Handle<Map> map)
};
+class HLoadPixelArrayElement: public HBinaryOperation {
+ public:
+ HLoadPixelArrayElement(HValue* external_elements, HValue* key)
+ : HBinaryOperation(external_elements, key) {
+ set_representation(Representation::Integer32());
+ SetFlag(kDependsOnPixelArrayElements);
+ // Native code could change the pixel array.
+ SetFlag(kDependsOnCalls);
+ SetFlag(kUseGVN);
+ }
+
+ virtual void PrintDataTo(StringStream* stream) const;
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ // The key is supposed to be Integer32, but the base pointer
+ // for the element load is a naked pointer.
+ return (index == 1) ? Representation::Integer32()
+ : Representation::External();
+ }
+
+ HValue* external_pointer() const { return OperandAt(0); }
+ HValue* key() const { return OperandAt(1); }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
+ "load_pixel_array_element")
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
class HLoadKeyedGeneric: public HLoadKeyed {
public:
HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
}
+HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
+ HValue* key,
+ Property* expr) {
+ ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
+ AddInstruction(new HCheckNonSmi(object));
+ Handle<Map> map = expr->GetMonomorphicReceiverType();
+ ASSERT(!map->has_fast_elements());
+ ASSERT(map->has_pixel_array_elements());
+ AddInstruction(new HCheckMap(object, map));
+ HLoadElements* elements = new HLoadElements(object);
+ AddInstruction(elements);
+ HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
+ AddInstruction(new HBoundsCheck(key, length));
+ HLoadPixelArrayExternalPointer* external_elements =
+ new HLoadPixelArrayExternalPointer(elements);
+ AddInstruction(external_elements);
+ HLoadPixelArrayElement* pixel_array_value =
+ new HLoadPixelArrayElement(external_elements, key);
+ return pixel_array_value;
+}
+
+
HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
HValue* key,
HValue* value) {
HValue* key = Pop();
HValue* obj = Pop();
- bool is_fast_elements = expr->IsMonomorphic() &&
- expr->GetMonomorphicReceiverType()->has_fast_elements();
-
- instr = is_fast_elements
- ? BuildLoadKeyedFastElement(obj, key, expr)
- : BuildLoadKeyedGeneric(obj, key);
+ 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 = BuildLoadKeyedPixelArrayElement(obj, key, expr);
+ } else if (receiver_type->has_fast_elements()) {
+ instr = BuildLoadKeyedFastElement(obj, key, expr);
+ }
+ }
+ if (instr == NULL) {
+ instr = BuildLoadKeyedGeneric(obj, key);
+ }
}
instr->set_position(expr->position());
ast_context()->ReturnInstruction(instr, expr->id());
HInstruction* BuildLoadKeyedFastElement(HValue* object,
HValue* key,
Property* expr);
+ HInstruction* BuildLoadKeyedPixelArrayElement(HValue* object,
+ HValue* key,
+ Property* expr);
HInstruction* BuildLoadKeyedGeneric(HValue* object,
HValue* key);
}
+void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->InputAt(0));
+ __ mov(result, FieldOperand(array, PixelArray::kLengthOffset));
+}
+
+
void LCodeGen::DoValueOf(LValueOf* instr) {
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
void LCodeGen::DoLoadElements(LLoadElements* instr) {
- ASSERT(instr->result()->Equals(instr->InputAt(0)));
- Register reg = ToRegister(instr->InputAt(0));
- __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset));
+ Register result = ToRegister(instr->result());
+ Register input = ToRegister(instr->InputAt(0));
+ __ mov(result, FieldOperand(input, JSObject::kElementsOffset));
if (FLAG_debug_code) {
NearLabel done;
- __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ __ cmp(FieldOperand(result, HeapObject::kMapOffset),
Immediate(Factory::fixed_array_map()));
__ j(equal, &done);
- __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ __ cmp(FieldOperand(result, HeapObject::kMapOffset),
+ Immediate(Factory::pixel_array_map()));
+ __ j(equal, &done);
+ __ cmp(FieldOperand(result, HeapObject::kMapOffset),
Immediate(Factory::fixed_cow_array_map()));
- __ Check(equal, "Check for fast elements failed.");
+ __ Check(equal, "Check for fast elements or pixel array failed.");
__ bind(&done);
}
}
+void LCodeGen::DoLoadPixelArrayExternalPointer(
+ LLoadPixelArrayExternalPointer* instr) {
+ Register result = ToRegister(instr->result());
+ Register input = ToRegister(instr->InputAt(0));
+ __ mov(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+}
+
+
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
Register arguments = ToRegister(instr->arguments());
Register length = ToRegister(instr->length());
}
+void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
+ Register external_elements = ToRegister(instr->external_pointer());
+ Register key = ToRegister(instr->key());
+ Register result = ToRegister(instr->result());
+ ASSERT(result.is(external_elements));
+
+ // Load the result.
+ __ movzx_b(result, Operand(external_elements, key, times_1, 0));
+}
+
+
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
}
+LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LPixelArrayLength(array));
+}
+
+
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
LValueOf* result = new LValueOf(object, TempRegister());
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineSameAsFirst(new LLoadElements(input));
+ return DefineAsRegister(new LLoadElements(input));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
+ HLoadPixelArrayExternalPointer* instr) {
+ LOperand* input = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
}
}
+LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
+ HLoadPixelArrayElement* instr) {
+ ASSERT(instr->representation().IsInteger32());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* external_pointer =
+ UseRegisterAtStart(instr->external_pointer());
+ LOperand* key = UseRegisterAtStart(instr->key());
+ LLoadPixelArrayElement* result =
+ new LLoadPixelArrayElement(external_pointer, key);
+ return DefineSameAsFirst(result);
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), edx);
V(LoadKeyedGeneric) \
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> {
+ public:
+ explicit LPixelArrayLength(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+};
+
+
class LFixedArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayLength(LOperand* value) {
};
+class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
+ "load-pixel-array-external-pointer")
+};
+
+
class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
};
+class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+ inputs_[0] = external_pointer;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
+ "load-pixel-array-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+
+ LOperand* external_pointer() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> {
public:
LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
}
+MaybeObject* Map::GetPixelArrayElementsMap() {
+ if (has_pixel_array_elements()) return this;
+ // TODO(danno): Special case empty object map (or most common case)
+ // to return a pre-canned pixel array map.
+ Object* obj;
+ { MaybeObject* maybe_obj = CopyDropTransitions();
+ if (!maybe_obj->ToObject(&obj)) return maybe_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();
+ return new_map;
+}
+
+
ACCESSORS(Map, instance_descriptors, DescriptorArray,
kInstanceDescriptorsOffset)
ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
return ((1 << kHasFastElements) & bit_field2()) != 0;
}
+ // Tells whether an instance has pixel array elements.
+ inline void set_has_pixel_array_elements(bool value) {
+ if (value) {
+ set_bit_field2(bit_field2() | (1 << kHasPixelArrayElements));
+ } else {
+ set_bit_field2(bit_field2() & ~(1 << kHasPixelArrayElements));
+ }
+ }
+
+ inline bool has_pixel_array_elements() {
+ return ((1 << kHasPixelArrayElements) & bit_field2()) != 0;
+ }
+
// Tells whether the map is attached to SharedFunctionInfo
// (for inobject slack tracking).
inline void set_attached_to_shared_function_info(bool value);
// 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 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;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
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) \
/* How is the generic keyed-load stub used? */ \
SC(keyed_load_generic_smi, V8.KeyedLoadGenericSmi) \
SC(keyed_load_generic_symbol, V8.KeyedLoadGenericSymbol) \
}
+void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->InputAt(0));
+ __ movq(result, FieldOperand(array, PixelArray::kLengthOffset));
+}
+
+
void LCodeGen::DoValueOf(LValueOf* instr) {
Abort("Unimplemented: %s", "DoValueOf");
}
void LCodeGen::DoLoadElements(LLoadElements* instr) {
- ASSERT(instr->result()->Equals(instr->InputAt(0)));
- Register reg = ToRegister(instr->InputAt(0));
- __ movq(reg, FieldOperand(reg, JSObject::kElementsOffset));
+ Register result = ToRegister(instr->result());
+ Register input = ToRegister(instr->InputAt(0));
+ __ movq(result, FieldOperand(input, JSObject::kElementsOffset));
if (FLAG_debug_code) {
NearLabel done;
- __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
Factory::fixed_array_map());
__ j(equal, &done);
- __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
+ Factory::pixel_array_map());
+ __ j(equal, &done);
+ __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
Factory::fixed_cow_array_map());
__ Check(equal, "Check for fast elements failed.");
__ bind(&done);
}
+void LCodeGen::DoLoadPixelArrayExternalPointer(
+ LLoadPixelArrayExternalPointer* instr) {
+ Register result = ToRegister(instr->result());
+ Register input = ToRegister(instr->InputAt(0));
+ __ movq(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+}
+
+
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
Abort("Unimplemented: %s", "DoAccessArgumentsAt");
}
}
+void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
+ Register external_elements = ToRegister(instr->external_pointer());
+ Register key = ToRegister(instr->key());
+ Register result = ToRegister(instr->result());
+ ASSERT(result.is(external_elements));
+
+ // Load the result.
+ __ movzxbq(result, Operand(external_elements, key, times_1, 0));
+}
+
+
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
}
}
+LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LPixelArrayLength(array));
+}
+
+
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
Abort("Unimplemented: %s", "DoValueOf");
return NULL;
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineSameAsFirst(new LLoadElements(input));
+ return DefineAsRegister(new LLoadElements(input));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
+ HLoadPixelArrayExternalPointer* instr) {
+ LOperand* input = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
}
}
+LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
+ HLoadPixelArrayElement* instr) {
+ ASSERT(instr->representation().IsInteger32());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* external_pointer =
+ UseRegisterAtStart(instr->external_pointer());
+ LOperand* key = UseRegisterAtStart(instr->key());
+ LLoadPixelArrayElement* result =
+ new LLoadPixelArrayElement(external_pointer, key);
+ return DefineSameAsFirst(result);
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
return NULL;
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(LoadFunctionPrototype) \
+ V(LoadPixelArrayElement) \
+ V(LoadPixelArrayExternalPointer) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
V(ObjectLiteral) \
V(OsrEntry) \
V(Parameter) \
+ V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
};
+class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LPixelArrayLength(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+};
+
+
class LFixedArrayLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayLength(LOperand* value) {
};
+class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
+ "load-pixel-array-external-pointer")
+};
+
+
class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
};
+class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+ inputs_[0] = external_pointer;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
+ "load-pixel-array-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+
+ LOperand* external_pointer() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
"result");
CHECK_EQ(32640, result->Int32Value());
+ // Make sure that pixel array loads are optimized by crankshaft.
+ result = CompileRun("function pa_load(p) {"
+ " var sum = 0;"
+ " for (var i=0; i<256; ++i) {"
+ " sum += p[i];"
+ " }"
+ " return sum; "
+ "}"
+ "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
+ "for (var i = 0; i < 10000; ++i) {"
+ " result = pa_load(pixels);"
+ "}"
+ "result");
+ CHECK_EQ(32640, result->Int32Value());
+
free(pixel_data);
}