Use shorter TryAllocate instruction sequence on ARM/ARM64/MIPS.
On these architectures it's preferable to load Scavenger address into the register and then access top/end fields through this register instead of loading addresses of those fields as immediates --- which takes either two instructions or a memory load through a pool pointer. Cleanup boxing slow-paths in the optimizing compiler. We had tons of duplicated code that was essentially doing the same thing. BUG= R=johnmccutchan@google.com, regis@google.com Review URL: https://codereview.chromium.org//410333003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@38539 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -210,7 +210,7 @@ void Assembler::Unreachable(const char* message) {
|
||||
|
||||
|
||||
void Assembler::Comment(const char* format, ...) {
|
||||
if (FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized) {
|
||||
if (EmittingComments()) {
|
||||
char buffer[1024];
|
||||
|
||||
va_list args;
|
||||
@@ -225,6 +225,11 @@ void Assembler::Comment(const char* format, ...) {
|
||||
}
|
||||
|
||||
|
||||
bool Assembler::EmittingComments() {
|
||||
return FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized;
|
||||
}
|
||||
|
||||
|
||||
const Code::Comments& Assembler::GetCodeComments() const {
|
||||
Code::Comments& comments = Code::Comments::New(comments_.length());
|
||||
|
||||
|
||||
@@ -3146,23 +3146,24 @@ void Assembler::TryAllocate(const Class& cls,
|
||||
Register temp_reg) {
|
||||
ASSERT(failure != NULL);
|
||||
if (FLAG_inline_alloc) {
|
||||
Heap* heap = Isolate::Current()->heap();
|
||||
ASSERT(instance_reg != temp_reg);
|
||||
ASSERT(temp_reg != IP);
|
||||
const intptr_t instance_size = cls.instance_size();
|
||||
LoadImmediate(instance_reg, heap->TopAddress());
|
||||
ldr(instance_reg, Address(instance_reg, 0));
|
||||
|
||||
LoadImmediate(temp_reg, Isolate::Current()->heap()->NewSpaceAddress());
|
||||
|
||||
ldr(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
AddImmediate(instance_reg, instance_size);
|
||||
|
||||
// instance_reg: potential next object start.
|
||||
LoadImmediate(IP, heap->EndAddress());
|
||||
ldr(IP, Address(IP, 0));
|
||||
ldr(IP, Address(temp_reg, Scavenger::end_offset()));
|
||||
cmp(IP, Operand(instance_reg));
|
||||
// fail if heap end unsigned less than or equal to instance_reg.
|
||||
b(failure, LS);
|
||||
|
||||
// Successfully allocated the object, now update top to point to
|
||||
// next object start and store the class in the class field of object.
|
||||
LoadImmediate(IP, heap->TopAddress());
|
||||
str(instance_reg, Address(IP, 0));
|
||||
str(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
|
||||
ASSERT(instance_size >= kHeapObjectTag);
|
||||
AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
|
||||
|
||||
@@ -337,6 +337,7 @@ class Assembler : public ValueObject {
|
||||
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
||||
const Code::Comments& GetCodeComments() const;
|
||||
|
||||
|
||||
@@ -1376,26 +1376,25 @@ void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
|
||||
void Assembler::TryAllocate(const Class& cls,
|
||||
Label* failure,
|
||||
Register instance_reg,
|
||||
Register temp_reg,
|
||||
Register pp) {
|
||||
ASSERT(failure != NULL);
|
||||
if (FLAG_inline_alloc) {
|
||||
Heap* heap = Isolate::Current()->heap();
|
||||
const intptr_t instance_size = cls.instance_size();
|
||||
LoadImmediate(instance_reg, heap->TopAddress(), pp);
|
||||
ldr(instance_reg, Address(instance_reg));
|
||||
LoadImmediate(temp_reg, heap->NewSpaceAddress(), pp);
|
||||
ldr(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
AddImmediate(instance_reg, instance_reg, instance_size, pp);
|
||||
|
||||
// instance_reg: potential next object start.
|
||||
LoadImmediate(TMP, heap->EndAddress(), pp);
|
||||
ldr(TMP, Address(TMP));
|
||||
ldr(TMP, Address(temp_reg, Scavenger::end_offset()));
|
||||
CompareRegisters(TMP, instance_reg);
|
||||
// fail if heap end unsigned less than or equal to instance_reg.
|
||||
b(failure, LS);
|
||||
|
||||
// Successfully allocated the object, now update top to point to
|
||||
// next object start and store the class in the class field of object.
|
||||
LoadImmediate(TMP, heap->TopAddress(), pp);
|
||||
str(instance_reg, Address(TMP));
|
||||
str(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
|
||||
ASSERT(instance_size >= kHeapObjectTag);
|
||||
AddImmediate(
|
||||
|
||||
@@ -431,6 +431,7 @@ class Assembler : public ValueObject {
|
||||
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
||||
const Code::Comments& GetCodeComments() const;
|
||||
|
||||
@@ -1217,6 +1218,7 @@ class Assembler : public ValueObject {
|
||||
void TryAllocate(const Class& cls,
|
||||
Label* failure,
|
||||
Register instance_reg,
|
||||
Register temp_reg,
|
||||
Register pp);
|
||||
|
||||
Address ElementAddressForIntIndex(bool is_external,
|
||||
|
||||
@@ -821,6 +821,8 @@ class Assembler : public ValueObject {
|
||||
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
||||
const Code::Comments& GetCodeComments() const;
|
||||
|
||||
static const char* RegisterName(Register reg);
|
||||
|
||||
@@ -858,20 +858,19 @@ void Assembler::TryAllocate(const Class& cls,
|
||||
if (FLAG_inline_alloc) {
|
||||
Heap* heap = Isolate::Current()->heap();
|
||||
const intptr_t instance_size = cls.instance_size();
|
||||
LoadImmediate(instance_reg, heap->TopAddress());
|
||||
lw(instance_reg, Address(instance_reg, 0));
|
||||
|
||||
LoadImmediate(temp_reg, heap->NewSpaceAddress());
|
||||
lw(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
AddImmediate(instance_reg, instance_size);
|
||||
|
||||
// instance_reg: potential next object start.
|
||||
LoadImmediate(TMP, heap->EndAddress());
|
||||
lw(TMP, Address(TMP, 0));
|
||||
lw(TMP, Address(temp_reg, Scavenger::end_offset()));
|
||||
// Fail if heap end unsigned less than or equal to instance_reg.
|
||||
BranchUnsignedLessEqual(TMP, instance_reg, failure);
|
||||
|
||||
// Successfully allocated the object, now update top to point to
|
||||
// next object start and store the class in the class field of object.
|
||||
LoadImmediate(TMP, heap->TopAddress());
|
||||
sw(instance_reg, Address(TMP, 0));
|
||||
sw(instance_reg, Address(temp_reg, Scavenger::top_offset()));
|
||||
|
||||
ASSERT(instance_size >= kHeapObjectTag);
|
||||
AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
|
||||
|
||||
@@ -227,6 +227,7 @@ class Assembler : public ValueObject {
|
||||
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
||||
const Code::Comments& GetCodeComments() const;
|
||||
|
||||
|
||||
@@ -770,6 +770,8 @@ class Assembler : public ValueObject {
|
||||
void Bind(Label* label);
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
||||
const Code::Comments& GetCodeComments() const;
|
||||
|
||||
intptr_t CodeSize() const { return buffer_.Size(); }
|
||||
|
||||
@@ -94,6 +94,8 @@ FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler,
|
||||
may_reoptimize_(false),
|
||||
double_class_(Class::ZoneHandle(
|
||||
isolate_->object_store()->double_class())),
|
||||
mint_class_(Class::ZoneHandle(
|
||||
isolate_->object_store()->mint_class())),
|
||||
float32x4_class_(Class::ZoneHandle(
|
||||
isolate_->object_store()->float32x4_class())),
|
||||
float64x2_class_(Class::ZoneHandle(
|
||||
|
||||
@@ -445,6 +445,7 @@ class FlowGraphCompiler : public ValueObject {
|
||||
void FinalizeStaticCallTargetsTable(const Code& code);
|
||||
|
||||
const Class& double_class() const { return double_class_; }
|
||||
const Class& mint_class() const { return mint_class_; }
|
||||
const Class& float32x4_class() const { return float32x4_class_; }
|
||||
const Class& float64x2_class() const { return float64x2_class_; }
|
||||
const Class& int32x4_class() const { return int32x4_class_; }
|
||||
@@ -611,6 +612,7 @@ class FlowGraphCompiler : public ValueObject {
|
||||
bool may_reoptimize_;
|
||||
|
||||
const Class& double_class_;
|
||||
const Class& mint_class_;
|
||||
const Class& float32x4_class_;
|
||||
const Class& float64x2_class_;
|
||||
const Class& int32x4_class_;
|
||||
|
||||
@@ -164,6 +164,7 @@ class Heap {
|
||||
uword TopAddress();
|
||||
uword EndAddress();
|
||||
static intptr_t new_space_offset() { return OFFSET_OF(Heap, new_space_); }
|
||||
uword NewSpaceAddress() const { return reinterpret_cast<uword>(new_space_); }
|
||||
|
||||
// Initialize the heap and register it with the isolate.
|
||||
static void Init(Isolate* isolate,
|
||||
|
||||
@@ -1827,17 +1827,24 @@ void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
class BoxAllocationSlowPath : public SlowPathCode {
|
||||
public:
|
||||
StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
|
||||
const Class& cls)
|
||||
: instruction_(instruction), cls_(cls) { }
|
||||
BoxAllocationSlowPath(Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result)
|
||||
: instruction_(instruction),
|
||||
cls_(cls),
|
||||
result_(result) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
|
||||
__ Comment("StoreInstanceFieldSlowPath");
|
||||
if (Assembler::EmittingComments()) {
|
||||
__ Comment("%s slow path allocation of %s",
|
||||
instruction_->DebugName(),
|
||||
String::Handle(cls_.PrettyName()).ToCString());
|
||||
}
|
||||
__ Bind(entry_label());
|
||||
|
||||
const Code& stub =
|
||||
@@ -1845,22 +1852,40 @@ class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
locs->live_registers()->Remove(locs->temp(0));
|
||||
|
||||
locs->live_registers()->Remove(Location::RegisterLocation(result_));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->temp(0).reg(), R0);
|
||||
__ MoveRegister(result_, R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
static void Allocate(FlowGraphCompiler* compiler,
|
||||
Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result,
|
||||
Register temp) {
|
||||
BoxAllocationSlowPath* slow_path =
|
||||
new BoxAllocationSlowPath(instruction, cls, result);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(cls,
|
||||
slow_path->entry_label(),
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
StoreInstanceFieldInstr* instruction_;
|
||||
Instruction* instruction_;
|
||||
const Class& cls_;
|
||||
Register result_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1899,6 +1924,28 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
static void EnsureMutableBox(FlowGraphCompiler* compiler,
|
||||
StoreInstanceFieldInstr* instruction,
|
||||
Register box_reg,
|
||||
const Class& cls,
|
||||
Register instance_reg,
|
||||
intptr_t offset,
|
||||
Register temp) {
|
||||
Label done;
|
||||
__ ldr(box_reg, FieldAddress(instance_reg, offset));
|
||||
__ CompareImmediate(box_reg,
|
||||
reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ b(&done, NE);
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, instruction, cls, box_reg, temp);
|
||||
|
||||
__ MoveRegister(temp, box_reg);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset, temp);
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label skip_store;
|
||||
|
||||
@@ -1926,15 +1973,8 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, *cls);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(*cls,
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, *cls, temp, temp2);
|
||||
__ MoveRegister(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
} else {
|
||||
@@ -2005,72 +2045,39 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_double);
|
||||
Label copy_double;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->double_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareImmediate(temp,
|
||||
reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ b(©_double, NE);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ MoveRegister(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
__ Bind(©_double);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->double_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp);
|
||||
__ b(&skip_store);
|
||||
}
|
||||
|
||||
{
|
||||
__ Bind(&store_float32x4);
|
||||
Label copy_float32x4;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareImmediate(temp,
|
||||
reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ b(©_float32x4, NE);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ MoveRegister(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
__ Bind(©_float32x4);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float32x4_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp);
|
||||
__ b(&skip_store);
|
||||
}
|
||||
|
||||
{
|
||||
__ Bind(&store_float64x2);
|
||||
Label copy_float64x2;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float64x2_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareImmediate(temp,
|
||||
reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ b(©_float64x2, NE);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ MoveRegister(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
__ Bind(©_float64x2);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float64x2_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp);
|
||||
__ b(&skip_store);
|
||||
}
|
||||
@@ -2306,111 +2313,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class BoxDoubleSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxDoubleSlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxDoubleSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& double_class = compiler->double_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(double_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat32x4SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float32x4_class = compiler->float32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), Operand(R0));
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat64x2SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat64x2SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat64x2SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float64x2_class = compiler->float64x2_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float64x2_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), Operand(R0));
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
@@ -2511,14 +2413,12 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_double);
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->double_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ CopyDoubleField(result_reg, temp, TMP, temp2, value);
|
||||
__ b(&done);
|
||||
@@ -2526,14 +2426,12 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float32x4);
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->float32x4_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value);
|
||||
__ b(&done);
|
||||
@@ -2541,14 +2439,12 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float64x2);
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->float64x2_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value);
|
||||
__ b(&done);
|
||||
@@ -3387,17 +3283,15 @@ LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg());
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->double_class(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
|
||||
}
|
||||
|
||||
@@ -3475,19 +3369,16 @@ LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const QRegister value = locs()->in(0).fpu_reg();
|
||||
const DRegister dvalue0 = EvenDRegisterOf(value);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ Bind(slow_path->exit_label());
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->float32x4_class(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ StoreMultipleDToOffset(dvalue0, 2, out_reg,
|
||||
Float32x4::value_offset() - kHeapObjectTag);
|
||||
}
|
||||
@@ -3546,19 +3437,16 @@ LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const QRegister value = locs()->in(0).fpu_reg();
|
||||
const DRegister dvalue0 = EvenDRegisterOf(value);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ Bind(slow_path->exit_label());
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->float64x2_class(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ StoreMultipleDToOffset(dvalue0, 2, out_reg,
|
||||
Float64x2::value_offset() - kHeapObjectTag);
|
||||
}
|
||||
@@ -3616,54 +3504,17 @@ LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
class BoxInt32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxInt32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& int32x4_class = compiler->int32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(int32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), Operand(R0));
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
BoxInt32x4Instr* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const QRegister value = locs()->in(0).fpu_reg();
|
||||
const DRegister dvalue0 = EvenDRegisterOf(value);
|
||||
|
||||
__ TryAllocate(compiler->int32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->int32x4_class(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ StoreMultipleDToOffset(dvalue0, 2, out_reg,
|
||||
Int32x4::value_offset() - kHeapObjectTag);
|
||||
}
|
||||
@@ -5880,41 +5731,6 @@ LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
class BoxIntegerSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxIntegerSlowPath(Definition* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxIntegerSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& mint_class =
|
||||
Class::ZoneHandle(isolate->object_store()->mint_class());
|
||||
const Code& stub =
|
||||
Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), Operand(R0));
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Definition* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
if (is_smi()) {
|
||||
PairLocation* value_pair = locs()->in(0).AsPairLocation();
|
||||
@@ -5925,8 +5741,6 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
PairLocation* value_pair = locs()->in(0).AsPairLocation();
|
||||
Register value_lo = value_pair->At(0).reg();
|
||||
Register value_hi = value_pair->At(1).reg();
|
||||
@@ -5964,12 +5778,12 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
// Not a smi. Box it.
|
||||
__ Bind(¬_smi);
|
||||
__ TryAllocate(
|
||||
Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
||||
slow_path->entry_label(),
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->mint_class(),
|
||||
out_reg,
|
||||
tmp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ StoreToOffset(kWord,
|
||||
value_lo,
|
||||
out_reg,
|
||||
@@ -6447,8 +6261,6 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
Register value = locs()->in(0).reg();
|
||||
Register out = locs()->out(0).reg();
|
||||
Register temp = locs()->temp(0).reg();
|
||||
@@ -6467,12 +6279,12 @@ void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ b(&done);
|
||||
__ Bind(¬_smi);
|
||||
// Allocate a mint.
|
||||
__ TryAllocate(
|
||||
Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
||||
slow_path->entry_label(),
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler,
|
||||
this,
|
||||
compiler->mint_class(),
|
||||
out,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
// Copy low word into mint.
|
||||
__ StoreToOffset(kWord,
|
||||
value,
|
||||
|
||||
@@ -1564,17 +1564,24 @@ void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
class BoxAllocationSlowPath : public SlowPathCode {
|
||||
public:
|
||||
StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
|
||||
const Class& cls)
|
||||
: instruction_(instruction), cls_(cls) { }
|
||||
BoxAllocationSlowPath(Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result)
|
||||
: instruction_(instruction),
|
||||
cls_(cls),
|
||||
result_(result) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
|
||||
__ Comment("StoreInstanceFieldSlowPath");
|
||||
if (Assembler::EmittingComments()) {
|
||||
__ Comment("%s slow path allocation of %s",
|
||||
instruction_->DebugName(),
|
||||
String::Handle(cls_.PrettyName()).ToCString());
|
||||
}
|
||||
__ Bind(entry_label());
|
||||
|
||||
const Code& stub =
|
||||
@@ -1582,25 +1589,63 @@ class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
locs->live_registers()->Remove(locs->temp(0));
|
||||
|
||||
locs->live_registers()->Remove(Location::RegisterLocation(result_));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->temp(0).reg(), R0);
|
||||
__ mov(result_, R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
static void Allocate(FlowGraphCompiler* compiler,
|
||||
Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result,
|
||||
Register temp) {
|
||||
BoxAllocationSlowPath* slow_path =
|
||||
new BoxAllocationSlowPath(instruction, cls, result);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(cls,
|
||||
slow_path->entry_label(),
|
||||
result,
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
StoreInstanceFieldInstr* instruction_;
|
||||
Instruction* instruction_;
|
||||
const Class& cls_;
|
||||
Register result_;
|
||||
};
|
||||
|
||||
|
||||
static void EnsureMutableBox(FlowGraphCompiler* compiler,
|
||||
StoreInstanceFieldInstr* instruction,
|
||||
Register box_reg,
|
||||
const Class& cls,
|
||||
Register instance_reg,
|
||||
intptr_t offset,
|
||||
Register temp) {
|
||||
Label done;
|
||||
__ LoadFieldFromOffset(box_reg, instance_reg, offset, PP);
|
||||
__ CompareObject(box_reg, Object::null_object(), PP);
|
||||
__ b(&done, NE);
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, instruction, cls, box_reg, temp);
|
||||
__ mov(temp, box_reg);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset, temp, PP);
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
@@ -1661,15 +1706,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, *cls);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(*cls,
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
|
||||
} else {
|
||||
@@ -1739,23 +1776,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_double);
|
||||
Label copy_double;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->double_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ b(©_double, NE);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
|
||||
__ Bind(©_double);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->double_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset(), PP);
|
||||
__ StoreDFieldToOffset(VTMP, temp, Double::value_offset(), PP);
|
||||
__ b(&skip_store);
|
||||
@@ -1763,23 +1790,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float32x4);
|
||||
Label copy_float32x4;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ b(©_float32x4, NE);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
|
||||
__ Bind(©_float32x4);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float32x4_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset(), PP);
|
||||
__ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset(), PP);
|
||||
__ b(&skip_store);
|
||||
@@ -1787,23 +1804,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float64x2);
|
||||
Label copy_float64x2;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float64x2_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ b(©_float64x2, NE);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
|
||||
__ Bind(©_float64x2);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float64x2_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset(), PP);
|
||||
__ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset(), PP);
|
||||
__ b(&skip_store);
|
||||
@@ -1939,111 +1946,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class BoxDoubleSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxDoubleSlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxDoubleSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& double_class = compiler->double_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(double_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat32x4SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float32x4_class = compiler->float32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat64x2SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat64x2SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat64x2SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float64x2_class = compiler->float64x2_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float64x2_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
@@ -2134,14 +2036,11 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_double);
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler,
|
||||
this,
|
||||
compiler->double_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
|
||||
__ LoadDFieldFromOffset(VTMP, temp, Double::value_offset(), PP);
|
||||
__ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset(), PP);
|
||||
@@ -2150,14 +2049,11 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float32x4);
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler,
|
||||
this,
|
||||
compiler->float32x4_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
|
||||
__ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset(), PP);
|
||||
__ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset(), PP);
|
||||
@@ -2166,14 +2062,11 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float64x2);
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler,
|
||||
this,
|
||||
compiler->float64x2_class(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
|
||||
__ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset(), PP);
|
||||
__ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset(), PP);
|
||||
@@ -2966,27 +2859,23 @@ void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = 0;
|
||||
const intptr_t kNumTemps = 1;
|
||||
LocationSummary* summary = new(isolate) LocationSummary(
|
||||
isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
||||
summary->set_in(0, Location::RequiresFpuRegister());
|
||||
summary->set_temp(0, Location::RequiresRegister());
|
||||
summary->set_out(0, Location::RequiresRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const Register temp_reg = locs()->temp(0).reg();
|
||||
const VRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), out_reg, temp_reg);
|
||||
__ StoreDFieldToOffset(value, out_reg, Double::value_offset(), PP);
|
||||
}
|
||||
|
||||
@@ -3043,28 +2932,23 @@ void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = 0;
|
||||
const intptr_t kNumTemps = 1;
|
||||
LocationSummary* summary = new(isolate) LocationSummary(
|
||||
isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
||||
summary->set_in(0, Location::RequiresFpuRegister());
|
||||
summary->set_temp(0, Location::RequiresRegister());
|
||||
summary->set_out(0, Location::RequiresRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const Register temp_reg = locs()->temp(0).reg();
|
||||
const VRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float32x4_class(), out_reg, temp_reg);
|
||||
__ StoreQFieldToOffset(value, out_reg, Float32x4::value_offset(), PP);
|
||||
}
|
||||
|
||||
@@ -3101,28 +2985,23 @@ void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = 0;
|
||||
const intptr_t kNumTemps = 1;
|
||||
LocationSummary* summary = new(isolate) LocationSummary(
|
||||
isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
||||
summary->set_in(0, Location::RequiresFpuRegister());
|
||||
summary->set_temp(0, Location::RequiresRegister());
|
||||
summary->set_out(0, Location::RequiresRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const Register temp_reg = locs()->temp(0).reg();
|
||||
const VRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float64x2_class(), out_reg, temp_reg);
|
||||
__ StoreQFieldToOffset(value, out_reg, Float64x2::value_offset(), PP);
|
||||
}
|
||||
|
||||
@@ -3159,63 +3038,22 @@ void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = 0;
|
||||
const intptr_t kNumTemps = 1;
|
||||
LocationSummary* summary = new(isolate) LocationSummary(
|
||||
isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
||||
summary->set_in(0, Location::RequiresFpuRegister());
|
||||
summary->set_temp(0, Location::RequiresRegister());
|
||||
summary->set_out(0, Location::RequiresRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
class BoxInt32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxInt32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& int32x4_class = compiler->int32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(int32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->out(0).reg(), R0);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
BoxInt32x4Instr* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Register out_reg = locs()->out(0).reg();
|
||||
const Register temp_reg = locs()->temp(0).reg();
|
||||
const VRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->int32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->int32x4_class(), out_reg, temp_reg);
|
||||
__ StoreQFieldToOffset(value, out_reg, Int32x4::value_offset(), PP);
|
||||
}
|
||||
|
||||
|
||||
@@ -1665,37 +1665,65 @@ void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
class BoxAllocationSlowPath : public SlowPathCode {
|
||||
public:
|
||||
StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
|
||||
const Class& cls)
|
||||
: instruction_(instruction), cls_(cls) { }
|
||||
BoxAllocationSlowPath(Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result)
|
||||
: instruction_(instruction),
|
||||
cls_(cls),
|
||||
result_(result) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("StoreInstanceFieldSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
|
||||
if (Assembler::EmittingComments()) {
|
||||
__ Comment("%s slow path allocation of %s",
|
||||
instruction_->DebugName(),
|
||||
String::Handle(cls_.PrettyName()).ToCString());
|
||||
}
|
||||
__ Bind(entry_label());
|
||||
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
isolate->stub_code()->GetAllocationStubForClass(cls_));
|
||||
Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
locs->live_registers()->Remove(locs->temp(0));
|
||||
|
||||
locs->live_registers()->Remove(Location::RegisterLocation(result_));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->temp(0).reg(), EAX);
|
||||
__ MoveRegister(result_, EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
static void Allocate(FlowGraphCompiler* compiler,
|
||||
Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result,
|
||||
Register temp) {
|
||||
BoxAllocationSlowPath* slow_path =
|
||||
new BoxAllocationSlowPath(instruction, cls, result);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(cls,
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
StoreInstanceFieldInstr* instruction_;
|
||||
Instruction* instruction_;
|
||||
const Class& cls_;
|
||||
Register result_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1734,6 +1762,29 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
static void EnsureMutableBox(FlowGraphCompiler* compiler,
|
||||
StoreInstanceFieldInstr* instruction,
|
||||
Register box_reg,
|
||||
const Class& cls,
|
||||
Register instance_reg,
|
||||
intptr_t offset,
|
||||
Register temp) {
|
||||
Label done;
|
||||
const Immediate& raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ movl(box_reg, FieldAddress(instance_reg, offset));
|
||||
__ cmpl(box_reg, raw_null);
|
||||
__ j(NOT_EQUAL, &done);
|
||||
BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
|
||||
__ movl(temp, box_reg);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset),
|
||||
temp);
|
||||
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label skip_store;
|
||||
|
||||
@@ -1761,16 +1812,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, *cls);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(*cls,
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
|
||||
__ movl(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
@@ -1842,30 +1884,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_double);
|
||||
Label copy_double;
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->double_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Immediate& raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ cmpl(temp, raw_null);
|
||||
__ j(NOT_EQUAL, ©_double);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movl(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_double);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->double_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
|
||||
__ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -1873,30 +1898,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float32x4);
|
||||
Label copy_float32x4;
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Immediate& raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ cmpl(temp, raw_null);
|
||||
__ j(NOT_EQUAL, ©_float32x4);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movl(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_float32x4);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float32x4_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
|
||||
__ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -1904,30 +1912,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float64x2);
|
||||
Label copy_float64x2;
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float64x2_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
const Immediate& raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ cmpl(temp, raw_null);
|
||||
__ j(NOT_EQUAL, ©_float64x2);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movl(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_float64x2);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float64x2_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset()));
|
||||
__ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -2161,110 +2152,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class BoxDoubleSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxDoubleSlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxDoubleSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& double_class = compiler->double_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(double_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat32x4SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float32x4_class = compiler->float32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat64x2SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat64x2SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat64x2SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float64x2_class = compiler->float64x2_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float64x2_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
@@ -2356,15 +2243,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_double);
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), result, temp);
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movsd(value, FieldAddress(temp, Double::value_offset()));
|
||||
__ movsd(FieldAddress(result, Double::value_offset()), value);
|
||||
@@ -2373,16 +2253,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float32x4);
|
||||
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float32x4_class(), result, temp);
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movups(value, FieldAddress(temp, Float32x4::value_offset()));
|
||||
__ movups(FieldAddress(result, Float32x4::value_offset()), value);
|
||||
@@ -2391,16 +2263,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float64x2);
|
||||
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float64x2_class(), result, temp);
|
||||
__ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movups(value, FieldAddress(temp, Float64x2::value_offset()));
|
||||
__ movups(FieldAddress(result, Float64x2::value_offset()), value);
|
||||
@@ -3359,18 +3223,10 @@ LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), out_reg, kNoRegister);
|
||||
__ movsd(FieldAddress(out_reg, Double::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3449,18 +3305,11 @@ LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float32x4_class(), out_reg, kNoRegister);
|
||||
__ movups(FieldAddress(out_reg, Float32x4::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3514,18 +3363,11 @@ LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float64x2_class(), out_reg, kNoRegister);
|
||||
__ movups(FieldAddress(out_reg, Float64x2::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3578,54 +3420,12 @@ LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
class BoxInt32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxInt32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& int32x4_class = compiler->int32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(int32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
BoxInt32x4Instr* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->int32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->int32x4_class(), out_reg, kNoRegister);
|
||||
__ movups(FieldAddress(out_reg, Int32x4::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -5703,41 +5503,6 @@ LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
class BoxIntegerSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxIntegerSlowPath(Definition* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxIntegerSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& mint_class =
|
||||
Class::ZoneHandle(isolate, isolate->object_store()->mint_class());
|
||||
const Code& stub =
|
||||
Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), EAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Definition* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
if (is_smi()) {
|
||||
PairLocation* value_pair = locs()->in(0).AsPairLocation();
|
||||
@@ -5748,8 +5513,6 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
PairLocation* value_pair = locs()->in(0).AsPairLocation();
|
||||
Register value_lo = value_pair->At(0).reg();
|
||||
Register value_hi = value_pair->At(1).reg();
|
||||
@@ -5777,15 +5540,11 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiTag(out_reg);
|
||||
__ jmp(&done);
|
||||
__ Bind(¬_smi);
|
||||
__ TryAllocate(
|
||||
Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
// 3. Restore lower half of input before using it.
|
||||
__ subl(value_lo, Immediate(0x40000000));
|
||||
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->mint_class(), out_reg, kNoRegister);
|
||||
__ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
|
||||
__ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
|
||||
__ Bind(&done);
|
||||
@@ -6338,8 +6097,6 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
Register value = locs()->in(0).reg();
|
||||
Register out = locs()->out(0).reg();
|
||||
ASSERT(value != out);
|
||||
@@ -6356,13 +6113,8 @@ void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ jmp(&done);
|
||||
__ Bind(¬_smi);
|
||||
// Allocate a mint.
|
||||
__ TryAllocate(
|
||||
Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->mint_class(), out, kNoRegister);
|
||||
// Copy low word into mint.
|
||||
__ movl(FieldAddress(out, Mint::value_offset()), value);
|
||||
// Zero high word.
|
||||
|
||||
@@ -1674,39 +1674,65 @@ void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
class BoxAllocationSlowPath : public SlowPathCode {
|
||||
public:
|
||||
StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
|
||||
const Class& cls)
|
||||
: instruction_(instruction), cls_(cls) { }
|
||||
BoxAllocationSlowPath(Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result)
|
||||
: instruction_(instruction),
|
||||
cls_(cls),
|
||||
result_(result) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
|
||||
__ Comment("StoreInstanceFieldSlowPath");
|
||||
if (Assembler::EmittingComments()) {
|
||||
__ Comment("%s slow path allocation of %s",
|
||||
instruction_->DebugName(),
|
||||
String::Handle(cls_.PrettyName()).ToCString());
|
||||
}
|
||||
__ Bind(entry_label());
|
||||
const Code& stub =
|
||||
Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
locs->live_registers()->Remove(locs->temp(0));
|
||||
locs->live_registers()->Remove(Location::RegisterLocation(result_));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ mov(locs->temp(0).reg(), V0);
|
||||
if (result_ != V0) {
|
||||
__ mov(result_, V0);
|
||||
}
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
static void Allocate(FlowGraphCompiler* compiler,
|
||||
Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result,
|
||||
Register temp) {
|
||||
BoxAllocationSlowPath* slow_path =
|
||||
new BoxAllocationSlowPath(instruction, cls, result);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(cls,
|
||||
slow_path->entry_label(),
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
StoreInstanceFieldInstr* instruction_;
|
||||
Instruction* instruction_;
|
||||
const Class& cls_;
|
||||
Register result_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1745,6 +1771,24 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
static void EnsureMutableBox(FlowGraphCompiler* compiler,
|
||||
StoreInstanceFieldInstr* instruction,
|
||||
Register box_reg,
|
||||
const Class& cls,
|
||||
Register instance_reg,
|
||||
intptr_t offset,
|
||||
Register temp) {
|
||||
Label done;
|
||||
__ lw(box_reg, FieldAddress(instance_reg, offset));
|
||||
__ BranchNotEqual(box_reg, reinterpret_cast<int32_t>(Object::null()),
|
||||
&done);
|
||||
BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
|
||||
__ mov(temp, box_reg);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset, temp);
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label skip_store;
|
||||
|
||||
@@ -1766,15 +1810,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, *cls);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(*cls,
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
} else {
|
||||
@@ -1821,25 +1857,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_double);
|
||||
Label copy_double;
|
||||
|
||||
__ lw(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()),
|
||||
©_double);
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->double_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ mov(temp2, temp);
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
|
||||
|
||||
__ Bind(©_double);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->double_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ LoadDFromOffset(fpu_temp,
|
||||
value_reg,
|
||||
Double::value_offset() - kHeapObjectTag);
|
||||
@@ -2083,43 +2107,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class BoxDoubleSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxDoubleSlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxDoubleSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& double_class = compiler->double_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(double_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
if (locs->out(0).reg() != V0) {
|
||||
__ mov(locs->out(0).reg(), V0);
|
||||
}
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ b(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
@@ -2194,14 +2181,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_double);
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
result_reg,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), result_reg, temp);
|
||||
__ lw(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
|
||||
__ StoreDToOffset(value,
|
||||
@@ -3046,17 +3027,11 @@ LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
DRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
out_reg,
|
||||
locs()->temp(0).reg());
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), out_reg, locs()->temp(0).reg());
|
||||
__ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
|
||||
}
|
||||
|
||||
|
||||
@@ -1506,38 +1506,64 @@ void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class StoreInstanceFieldSlowPath : public SlowPathCode {
|
||||
class BoxAllocationSlowPath : public SlowPathCode {
|
||||
public:
|
||||
StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
|
||||
const Class& cls)
|
||||
: instruction_(instruction), cls_(cls) { }
|
||||
BoxAllocationSlowPath(Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result)
|
||||
: instruction_(instruction),
|
||||
cls_(cls),
|
||||
result_(result) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("StoreInstanceFieldSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Code& stub = Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(cls_));
|
||||
|
||||
if (Assembler::EmittingComments()) {
|
||||
__ Comment("%s slow path allocation of %s",
|
||||
instruction_->DebugName(),
|
||||
String::Handle(cls_.PrettyName()).ToCString());
|
||||
}
|
||||
__ Bind(entry_label());
|
||||
|
||||
const Code& stub =
|
||||
Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
locs->live_registers()->Remove(locs->temp(0));
|
||||
|
||||
locs->live_registers()->Remove(Location::RegisterLocation(result_));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->temp(0).reg(), RAX);
|
||||
__ MoveRegister(result_, RAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
static void Allocate(FlowGraphCompiler* compiler,
|
||||
Instruction* instruction,
|
||||
const Class& cls,
|
||||
Register result) {
|
||||
BoxAllocationSlowPath* slow_path =
|
||||
new BoxAllocationSlowPath(instruction, cls, result);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(cls,
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
StoreInstanceFieldInstr* instruction_;
|
||||
Instruction* instruction_;
|
||||
const Class& cls_;
|
||||
Register result_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1576,6 +1602,27 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
static void EnsureMutableBox(FlowGraphCompiler* compiler,
|
||||
StoreInstanceFieldInstr* instruction,
|
||||
Register box_reg,
|
||||
const Class& cls,
|
||||
Register instance_reg,
|
||||
intptr_t offset,
|
||||
Register temp) {
|
||||
Label done;
|
||||
__ movq(box_reg, FieldAddress(instance_reg, offset));
|
||||
__ CompareObject(box_reg, Object::null_object(), PP);
|
||||
__ j(NOT_EQUAL, &done);
|
||||
BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg);
|
||||
__ movq(temp, box_reg);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset),
|
||||
temp);
|
||||
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label skip_store;
|
||||
|
||||
@@ -1603,16 +1650,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, *cls);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(*cls,
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp);
|
||||
__ movq(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
@@ -1682,27 +1720,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_double);
|
||||
Label copy_double;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->double_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ j(NOT_EQUAL, ©_double);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movq(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_double);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->double_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
|
||||
__ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -1710,27 +1734,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float32x4);
|
||||
Label copy_float32x4;
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ j(NOT_EQUAL, ©_float32x4);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movq(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_float32x4);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float32x4_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
|
||||
__ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -1738,28 +1748,13 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&store_float64x2);
|
||||
Label copy_float64x2;
|
||||
|
||||
StoreInstanceFieldSlowPath* slow_path =
|
||||
new StoreInstanceFieldSlowPath(this, compiler->float64x2_class());
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes_));
|
||||
__ CompareObject(temp, Object::null_object(), PP);
|
||||
__ j(NOT_EQUAL, ©_float64x2);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
temp,
|
||||
temp2);
|
||||
__ Bind(slow_path->exit_label());
|
||||
__ movq(temp2, temp);
|
||||
__ StoreIntoObject(instance_reg,
|
||||
FieldAddress(instance_reg, offset_in_bytes_),
|
||||
temp2);
|
||||
|
||||
__ Bind(©_float64x2);
|
||||
EnsureMutableBox(compiler,
|
||||
this,
|
||||
temp,
|
||||
compiler->float64x2_class(),
|
||||
instance_reg,
|
||||
offset_in_bytes_,
|
||||
temp2);
|
||||
__ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset()));
|
||||
__ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp);
|
||||
__ jmp(&skip_store);
|
||||
@@ -1994,111 +1989,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
|
||||
class BoxDoubleSlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxDoubleSlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxDoubleSlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& double_class = compiler->double_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(double_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), RAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat32x4SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float32x4_class = compiler->float32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), RAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
class BoxFloat64x2SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxFloat64x2SlowPath(Instruction* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxFloat64x2SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& float64x2_class = compiler->float64x2_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(float64x2_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), RAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
Instruction* instruction_;
|
||||
};
|
||||
|
||||
|
||||
LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
@@ -2189,15 +2079,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_double);
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), result);
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movsd(value, FieldAddress(temp, Double::value_offset()));
|
||||
__ movsd(FieldAddress(result, Double::value_offset()), value);
|
||||
@@ -2206,15 +2089,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float32x4);
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float32x4_class(), result);
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movups(value, FieldAddress(temp, Float32x4::value_offset()));
|
||||
__ movups(FieldAddress(result, Float32x4::value_offset()), value);
|
||||
@@ -2223,15 +2099,8 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
{
|
||||
__ Bind(&load_float64x2);
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
result,
|
||||
temp);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float64x2_class(), result);
|
||||
__ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
|
||||
__ movups(value, FieldAddress(temp, Float64x2::value_offset()));
|
||||
__ movups(FieldAddress(result, Float64x2::value_offset()), value);
|
||||
@@ -3197,18 +3066,11 @@ LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->double_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->double_class(), out_reg);
|
||||
__ movsd(FieldAddress(out_reg, Double::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3282,18 +3144,11 @@ LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float32x4_class(), out_reg);
|
||||
__ movups(FieldAddress(out_reg, Float32x4::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3339,18 +3194,11 @@ LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
|
||||
|
||||
|
||||
void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->float64x2_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
kNoRegister);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->float64x2_class(), out_reg);
|
||||
__ movups(FieldAddress(out_reg, Float64x2::value_offset()), value);
|
||||
}
|
||||
|
||||
@@ -3398,54 +3246,12 @@ LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
class BoxInt32x4SlowPath : public SlowPathCode {
|
||||
public:
|
||||
explicit BoxInt32x4SlowPath(BoxInt32x4Instr* instruction)
|
||||
: instruction_(instruction) { }
|
||||
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("BoxInt32x4SlowPath");
|
||||
__ Bind(entry_label());
|
||||
Isolate* isolate = compiler->isolate();
|
||||
StubCode* stub_code = isolate->stub_code();
|
||||
const Class& int32x4_class = compiler->int32x4_class();
|
||||
const Code& stub =
|
||||
Code::Handle(isolate,
|
||||
stub_code->GetAllocationStubForClass(int32x4_class));
|
||||
const ExternalLabel label(stub.EntryPoint());
|
||||
|
||||
LocationSummary* locs = instruction_->locs();
|
||||
ASSERT(!locs->live_registers()->Contains(locs->out(0)));
|
||||
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
compiler->GenerateCall(Scanner::kNoSourcePos, // No token position.
|
||||
&label,
|
||||
RawPcDescriptors::kOther,
|
||||
locs);
|
||||
__ MoveRegister(locs->out(0).reg(), RAX);
|
||||
compiler->RestoreLiveRegisters(locs);
|
||||
|
||||
__ jmp(exit_label());
|
||||
}
|
||||
|
||||
private:
|
||||
BoxInt32x4Instr* instruction_;
|
||||
};
|
||||
|
||||
|
||||
void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
BoxInt32x4SlowPath* slow_path = new BoxInt32x4SlowPath(this);
|
||||
compiler->AddSlowPathCode(slow_path);
|
||||
|
||||
Register out_reg = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
|
||||
__ TryAllocate(compiler->int32x4_class(),
|
||||
slow_path->entry_label(),
|
||||
Assembler::kFarJump,
|
||||
out_reg,
|
||||
PP);
|
||||
__ Bind(slow_path->exit_label());
|
||||
BoxAllocationSlowPath::Allocate(
|
||||
compiler, this, compiler->int32x4_class(), out_reg);
|
||||
__ movups(FieldAddress(out_reg, Int32x4::value_offset()), value);
|
||||
}
|
||||
|
||||
|
||||
@@ -427,6 +427,7 @@ void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) {
|
||||
__ TryAllocate(double_class,
|
||||
&fall_through,
|
||||
R0, // Result register.
|
||||
R1, // Temp register.
|
||||
kNoPP);
|
||||
__ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
|
||||
__ ret();
|
||||
@@ -1074,7 +1075,7 @@ static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
|
||||
}
|
||||
const Class& double_class = Class::Handle(
|
||||
Isolate::Current()->object_store()->double_class());
|
||||
__ TryAllocate(double_class, &fall_through, R0, kNoPP);
|
||||
__ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
|
||||
__ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
|
||||
__ ret();
|
||||
__ Bind(&fall_through);
|
||||
@@ -1116,7 +1117,7 @@ void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
|
||||
__ fmuld(V0, V0, V1);
|
||||
const Class& double_class = Class::Handle(
|
||||
Isolate::Current()->object_store()->double_class());
|
||||
__ TryAllocate(double_class, &fall_through, R0, kNoPP);
|
||||
__ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
|
||||
__ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
|
||||
__ ret();
|
||||
__ Bind(&fall_through);
|
||||
@@ -1134,7 +1135,7 @@ void Intrinsifier::Double_fromInteger(Assembler* assembler) {
|
||||
__ scvtfd(V0, R0);
|
||||
const Class& double_class = Class::Handle(
|
||||
Isolate::Current()->object_store()->double_class());
|
||||
__ TryAllocate(double_class, &fall_through, R0, kNoPP);
|
||||
__ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
|
||||
__ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
|
||||
__ ret();
|
||||
__ Bind(&fall_through);
|
||||
@@ -1214,7 +1215,7 @@ void Intrinsifier::Math_sqrt(Assembler* assembler) {
|
||||
__ fsqrtd(V0, V1);
|
||||
const Class& double_class = Class::Handle(
|
||||
Isolate::Current()->object_store()->double_class());
|
||||
__ TryAllocate(double_class, &fall_through, R0, kNoPP);
|
||||
__ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
|
||||
__ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
|
||||
__ ret();
|
||||
__ Bind(&is_smi);
|
||||
|
||||
Reference in New Issue
Block a user