Add LoadTaggedClassIdMayBeSmi to assembly and improve performance of inline cache stubs.
R=zra@google.com Review URL: https://codereview.chromium.org//313083008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@37011 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -1685,6 +1685,14 @@ void Assembler::CompareClassId(Register object,
|
||||
}
|
||||
|
||||
|
||||
void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
|
||||
tst(object, Operand(kSmiTagMask));
|
||||
LoadImmediate(result, Smi::RawValue(kSmiCid), EQ);
|
||||
LoadClassId(result, object, NE);
|
||||
SmiTag(result, NE);
|
||||
}
|
||||
|
||||
|
||||
static bool CanEncodeBranchOffset(int32_t offset) {
|
||||
ASSERT(Utils::IsAligned(offset, 4));
|
||||
return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
|
||||
|
||||
@@ -640,6 +640,7 @@ class Assembler : public ValueObject {
|
||||
void LoadClassById(Register result, Register class_id);
|
||||
void LoadClass(Register result, Register object, Register scratch);
|
||||
void CompareClassId(Register object, intptr_t class_id, Register scratch);
|
||||
void LoadTaggedClassIdMayBeSmi(Register result, Register object);
|
||||
|
||||
void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond = AL);
|
||||
void LoadFromOffset(OperandSize type,
|
||||
|
||||
@@ -1073,6 +1073,19 @@ void Assembler::CompareClassId(
|
||||
}
|
||||
|
||||
|
||||
void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
|
||||
Label load, done;
|
||||
tsti(object, kSmiTagMask);
|
||||
b(&load, NE);
|
||||
LoadImmediate(result, Smi::RawValue(kSmiCid), PP);
|
||||
b(&done);
|
||||
Bind(&load);
|
||||
LoadClassId(result, object, PP);
|
||||
SmiTag(result);
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
// Frame entry and exit.
|
||||
void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
|
||||
// Reserve space for arguments and align frame before entering
|
||||
|
||||
@@ -1170,6 +1170,7 @@ class Assembler : public ValueObject {
|
||||
void LoadClassById(Register result, Register class_id, Register pp);
|
||||
void LoadClass(Register result, Register object, Register pp);
|
||||
void CompareClassId(Register object, intptr_t class_id, Register pp);
|
||||
void LoadTaggedClassIdMayBeSmi(Register result, Register object);
|
||||
|
||||
void EnterFrame(intptr_t frame_size);
|
||||
void LeaveFrame();
|
||||
|
||||
@@ -2656,6 +2656,19 @@ void Assembler::CompareClassId(Register object,
|
||||
}
|
||||
|
||||
|
||||
void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
|
||||
testl(object, Immediate(kSmiTagMask));
|
||||
Label not_smi, done;
|
||||
j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
|
||||
movl(result, Immediate(Smi::RawValue(kSmiCid)));
|
||||
jmp(&done, Assembler::kNearJump);
|
||||
Bind(¬_smi);
|
||||
LoadClassId(result, object);
|
||||
SmiTag(result);
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
|
||||
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
|
||||
};
|
||||
|
||||
@@ -686,6 +686,8 @@ class Assembler : public ValueObject {
|
||||
|
||||
void CompareClassId(Register object, intptr_t class_id, Register scratch);
|
||||
|
||||
void LoadTaggedClassIdMayBeSmi(Register result, Register object);
|
||||
|
||||
/*
|
||||
* Misc. functionality
|
||||
*/
|
||||
|
||||
@@ -652,6 +652,19 @@ void Assembler::LoadClass(Register result, Register object) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
|
||||
Label load, done;
|
||||
andi(CMPRES1, object, Immediate(kSmiTagMask));
|
||||
bne(CMPRES1, ZR, &load);
|
||||
LoadImmediate(result, Smi::RawValue(kSmiCid));
|
||||
b(&done);
|
||||
Bind(&load);
|
||||
LoadClassId(result, object);
|
||||
SmiTag(result);
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::EnterFrame() {
|
||||
ASSERT(!in_delay_slot_);
|
||||
addiu(SP, SP, Immediate(-2 * kWordSize));
|
||||
|
||||
@@ -1183,6 +1183,7 @@ class Assembler : public ValueObject {
|
||||
void LoadClassId(Register result, Register object);
|
||||
void LoadClassById(Register result, Register class_id);
|
||||
void LoadClass(Register result, Register object);
|
||||
void LoadTaggedClassIdMayBeSmi(Register result, Register object);
|
||||
|
||||
void StoreIntoObject(Register object, // Object we are storing into.
|
||||
const Address& dest, // Where we are storing into.
|
||||
|
||||
@@ -3278,6 +3278,19 @@ void Assembler::CompareClassId(Register object, intptr_t class_id) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
|
||||
Label load, done;
|
||||
testq(object, Immediate(kSmiTagMask));
|
||||
j(NOT_ZERO, &load, Assembler::kNearJump);
|
||||
LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP);
|
||||
jmp(&done);
|
||||
Bind(&load);
|
||||
LoadClassId(result, object);
|
||||
SmiTag(result);
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
|
||||
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
|
||||
|
||||
@@ -737,6 +737,8 @@ class Assembler : public ValueObject {
|
||||
|
||||
void CompareClassId(Register object, intptr_t class_id);
|
||||
|
||||
void LoadTaggedClassIdMayBeSmi(Register result, Register object);
|
||||
|
||||
/*
|
||||
* Misc. functionality.
|
||||
*/
|
||||
|
||||
@@ -1232,16 +1232,10 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
||||
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
|
||||
const MegamorphicCache& cache =
|
||||
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
|
||||
Label not_smi, load_cache;
|
||||
__ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
|
||||
__ tst(R0, Operand(kSmiTagMask));
|
||||
__ LoadClassId(R0, R0, NE);
|
||||
__ SmiTag(R0, NE);
|
||||
__ mov(R0, Operand(Smi::RawValue(kSmiCid)), EQ);
|
||||
__ b(&load_cache, EQ);
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
|
||||
// R0: class ID of the receiver (smi).
|
||||
__ Bind(&load_cache);
|
||||
__ LoadObject(R1, cache);
|
||||
__ ldr(R2, FieldAddress(R1, MegamorphicCache::buckets_offset()));
|
||||
__ ldr(R1, FieldAddress(R1, MegamorphicCache::mask_offset()));
|
||||
|
||||
@@ -1238,19 +1238,10 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
||||
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
|
||||
const MegamorphicCache& cache =
|
||||
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
|
||||
Label not_smi, load_cache;
|
||||
__ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP);
|
||||
__ tsti(R0, kSmiTagMask);
|
||||
__ b(¬_smi, NE);
|
||||
__ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP);
|
||||
__ b(&load_cache);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(R0, R0, PP);
|
||||
__ SmiTag(R0);
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
|
||||
// R0: class ID of the receiver (smi).
|
||||
__ Bind(&load_cache);
|
||||
__ LoadObject(R1, cache, PP);
|
||||
__ LoadFieldFromOffset(R2, R1, MegamorphicCache::buckets_offset(), PP);
|
||||
__ LoadFieldFromOffset(R1, R1, MegamorphicCache::mask_offset(), PP);
|
||||
|
||||
@@ -1279,16 +1279,9 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
||||
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
|
||||
const MegamorphicCache& cache =
|
||||
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
|
||||
Label not_smi, load_cache;
|
||||
Label load_cache;
|
||||
__ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
|
||||
__ testl(EAX, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
|
||||
__ movl(EAX, Immediate(Smi::RawValue(kSmiCid)));
|
||||
__ jmp(&load_cache);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(EAX, EAX);
|
||||
__ SmiTag(EAX);
|
||||
__ LoadTaggedClassIdMayBeSmi(EAX, EAX);
|
||||
|
||||
// EAX: class ID of the receiver (smi).
|
||||
__ Bind(&load_cache);
|
||||
|
||||
@@ -1272,20 +1272,11 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
||||
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
|
||||
const MegamorphicCache& cache =
|
||||
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
|
||||
Label not_smi, load_cache;
|
||||
__ TraceSimMsg("MegamorphicInstanceCall");
|
||||
__ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
|
||||
__ andi(CMPRES1, T0, Immediate(kSmiTagMask));
|
||||
__ bne(CMPRES1, ZR, ¬_smi);
|
||||
__ LoadImmediate(T0, Smi::RawValue(kSmiCid));
|
||||
__ b(&load_cache);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(T0, T0);
|
||||
__ SmiTag(T0);
|
||||
__ LoadTaggedClassIdMayBeSmi(T0, T0);
|
||||
|
||||
// T0: class ID of the receiver (smi).
|
||||
__ Bind(&load_cache);
|
||||
__ LoadObject(T1, cache);
|
||||
__ lw(T2, FieldAddress(T1, MegamorphicCache::buckets_offset()));
|
||||
__ lw(T1, FieldAddress(T1, MegamorphicCache::mask_offset()));
|
||||
|
||||
@@ -1317,19 +1317,10 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
||||
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
|
||||
const MegamorphicCache& cache =
|
||||
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
|
||||
Label not_smi, load_cache;
|
||||
__ movq(RAX, Address(RSP, (argument_count - 1) * kWordSize));
|
||||
__ testq(RAX, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
|
||||
__ LoadImmediate(RAX, Immediate(Smi::RawValue(kSmiCid)), PP);
|
||||
__ jmp(&load_cache);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(RAX, RAX);
|
||||
__ SmiTag(RAX);
|
||||
__ LoadTaggedClassIdMayBeSmi(RAX, RAX);
|
||||
|
||||
// RAX: class ID of the receiver (smi).
|
||||
__ Bind(&load_cache);
|
||||
__ LoadObject(RBX, cache, PP);
|
||||
__ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
|
||||
__ movq(RBX, FieldAddress(RBX, MegamorphicCache::mask_offset()));
|
||||
|
||||
@@ -1053,10 +1053,7 @@ LocationSummary* LoadClassIdInstr::MakeLocationSummary(Isolate* isolate,
|
||||
void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register object = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
__ tst(object, Operand(kSmiTagMask));
|
||||
__ LoadImmediate(result, Smi::RawValue(kSmiCid), EQ);
|
||||
__ LoadClassId(result, object, NE);
|
||||
__ SmiTag(result, NE);
|
||||
__ LoadTaggedClassIdMayBeSmi(result, object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -901,15 +901,7 @@ LocationSummary* LoadClassIdInstr::MakeLocationSummary(Isolate* isolate,
|
||||
void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register object = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
Label load, done;
|
||||
__ tsti(object, kSmiTagMask);
|
||||
__ b(&load, NE);
|
||||
__ LoadImmediate(result, Smi::RawValue(kSmiCid), PP);
|
||||
__ b(&done);
|
||||
__ Bind(&load);
|
||||
__ LoadClassId(result, object, PP);
|
||||
__ SmiTag(result);
|
||||
__ Bind(&done);
|
||||
__ LoadTaggedClassIdMayBeSmi(result, object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -939,15 +939,7 @@ LocationSummary* LoadClassIdInstr::MakeLocationSummary(Isolate* isolate,
|
||||
void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register object = locs()->in(0).reg();
|
||||
Register result = locs()->out(0).reg();
|
||||
Label load, done;
|
||||
__ testl(object, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, &load, Assembler::kNearJump);
|
||||
__ movl(result, Immediate(Smi::RawValue(kSmiCid)));
|
||||
__ jmp(&done);
|
||||
__ Bind(&load);
|
||||
__ LoadClassId(result, object);
|
||||
__ SmiTag(result);
|
||||
__ Bind(&done);
|
||||
__ LoadTaggedClassIdMayBeSmi(result, object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1019,15 +1019,7 @@ LocationSummary* LoadClassIdInstr::MakeLocationSummary(Isolate* isolate,
|
||||
void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register object = locs()->in(0).reg();
|
||||
Register result = locs()->out(0).reg();
|
||||
Label load, done;
|
||||
__ andi(CMPRES1, object, Immediate(kSmiTagMask));
|
||||
__ bne(CMPRES1, ZR, &load);
|
||||
__ LoadImmediate(result, Smi::RawValue(kSmiCid));
|
||||
__ b(&done);
|
||||
__ Bind(&load);
|
||||
__ LoadClassId(result, object);
|
||||
__ SmiTag(result);
|
||||
__ Bind(&done);
|
||||
__ LoadTaggedClassIdMayBeSmi(result, object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -868,15 +868,7 @@ LocationSummary* LoadClassIdInstr::MakeLocationSummary(Isolate* isolate,
|
||||
void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register object = locs()->in(0).reg();
|
||||
Register result = locs()->out(0).reg();
|
||||
Label load, done;
|
||||
__ testq(object, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, &load, Assembler::kNearJump);
|
||||
__ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP);
|
||||
__ jmp(&done);
|
||||
__ Bind(&load);
|
||||
__ LoadClassId(result, object);
|
||||
__ SmiTag(result);
|
||||
__ Bind(&done);
|
||||
__ LoadTaggedClassIdMayBeSmi(result, object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1283,7 +1283,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Preserve return address, since LR is needed for subroutine call.
|
||||
__ mov(R8, Operand(LR));
|
||||
// Loop that checks if there is an IC data match.
|
||||
Label loop, update, test, found, get_class_id_as_smi;
|
||||
Label loop, update, test, found;
|
||||
// R5: IC data object (preserved).
|
||||
__ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
|
||||
// R6: ic_data_array with check entries: classes and target functions.
|
||||
@@ -1295,7 +1295,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
|
||||
__ sub(R7, R7, Operand(Smi::RawValue(1)));
|
||||
__ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi.
|
||||
__ bl(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
// R7: argument_count - 1 (smi).
|
||||
// R0: receiver's class ID (smi).
|
||||
__ ldr(R1, Address(R6, 0)); // First class id (smi) to check.
|
||||
@@ -1307,7 +1307,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// If not the first, load the next argument's class ID.
|
||||
__ AddImmediate(R0, R7, Smi::RawValue(-i));
|
||||
__ ldr(R0, Address(SP, R0, LSL, 1));
|
||||
__ bl(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
// R0: next argument class ID (smi).
|
||||
__ LoadFromOffset(kWord, R1, R6, i * kWordSize);
|
||||
// R1: next class ID to check (smi).
|
||||
@@ -1325,7 +1325,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Reload receiver class ID. It has not been destroyed when num_args == 1.
|
||||
if (num_args > 1) {
|
||||
__ ldr(R0, Address(SP, R7, LSL, 1));
|
||||
__ bl(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
}
|
||||
|
||||
const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
|
||||
@@ -1385,17 +1385,6 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
|
||||
__ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
|
||||
__ bx(R2);
|
||||
|
||||
// Instance in R0, return its class-id in R0 as Smi.
|
||||
__ Bind(&get_class_id_as_smi);
|
||||
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
__ tst(R0, Operand(kSmiTagMask));
|
||||
__ mov(R0, Operand(Smi::RawValue(kSmiCid)), EQ);
|
||||
__ bx(LR, EQ);
|
||||
__ LoadClassId(R0, R0);
|
||||
__ SmiTag(R0);
|
||||
__ bx(LR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1387,23 +1387,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
|
||||
// R0 <- [SP + (R7 << 3)]
|
||||
__ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
|
||||
|
||||
{
|
||||
// TODO(zra): Put this code in a subroutine call as with other architectures
|
||||
// when we have a bl(Label& l) instruction.
|
||||
// Instance in R0, return its class-id in R0 as Smi.
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
Label not_smi, done;
|
||||
__ tsti(R0, kSmiTagMask);
|
||||
__ b(¬_smi, NE);
|
||||
__ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
|
||||
__ b(&done);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(R0, R0, kNoPP);
|
||||
__ SmiTag(R0);
|
||||
__ Bind(&done);
|
||||
}
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
|
||||
// R7: argument_count - 1 (untagged).
|
||||
// R0: receiver's class ID (smi).
|
||||
@@ -1417,20 +1401,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ AddImmediate(R0, R7, -i, kNoPP);
|
||||
// R0 <- [SP + (R0 << 3)]
|
||||
__ ldr(R0, Address(SP, R0, UXTX, Address::Scaled));
|
||||
{
|
||||
// Instance in R0, return its class-id in R0 as Smi.
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
Label not_smi, done;
|
||||
__ tsti(R0, kSmiTagMask);
|
||||
__ b(¬_smi, NE);
|
||||
__ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
|
||||
__ b(&done);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(R0, R0, kNoPP);
|
||||
__ SmiTag(R0);
|
||||
__ Bind(&done);
|
||||
}
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
// R0: next argument class ID (smi).
|
||||
__ LoadFromOffset(R1, R6, i * kWordSize, kNoPP);
|
||||
// R1: next class ID to check (smi).
|
||||
@@ -1447,20 +1418,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Reload receiver class ID. It has not been destroyed when num_args == 1.
|
||||
if (num_args > 1) {
|
||||
__ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
|
||||
{
|
||||
// Instance in R0, return its class-id in R0 as Smi.
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
Label not_smi, done;
|
||||
__ tsti(R0, kSmiTagMask);
|
||||
__ b(¬_smi, NE);
|
||||
__ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
|
||||
__ b(&done);
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(R0, R0, kNoPP);
|
||||
__ SmiTag(R0);
|
||||
__ Bind(&done);
|
||||
}
|
||||
__ LoadTaggedClassIdMayBeSmi(R0, R0);
|
||||
}
|
||||
|
||||
const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
|
||||
|
||||
@@ -1321,7 +1321,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Load arguments descriptor into EDX.
|
||||
__ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
|
||||
// Loop that checks if there is an IC data match.
|
||||
Label loop, update, test, found, get_class_id_as_smi;
|
||||
Label loop, update, test, found;
|
||||
// ECX: IC data object (preserved).
|
||||
__ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
|
||||
// EBX: ic_data_array with check entries: classes and target functions.
|
||||
@@ -1332,7 +1332,8 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// arguments descriptor array and then access the receiver from the stack).
|
||||
__ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
|
||||
__ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi.
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(EAX, EAX);
|
||||
|
||||
// EAX: receiver's class ID (smi).
|
||||
__ movl(EDI, Address(EBX, 0)); // First class id (smi) to check.
|
||||
__ jmp(&test);
|
||||
@@ -1343,7 +1344,8 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// If not the first, load the next argument's class ID.
|
||||
__ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
|
||||
__ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize));
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(EAX, EAX);
|
||||
|
||||
// EAX: next argument class ID (smi).
|
||||
__ movl(EDI, Address(EBX, i * kWordSize));
|
||||
// EDI: next class ID to check (smi).
|
||||
@@ -1361,7 +1363,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
if (num_args > 1) {
|
||||
__ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
|
||||
__ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(EAX, EAX);
|
||||
}
|
||||
|
||||
const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
|
||||
@@ -1418,20 +1420,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
|
||||
__ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
||||
__ jmp(EBX);
|
||||
|
||||
// Instance in EAX, return its class-id in EAX as Smi.
|
||||
__ Bind(&get_class_id_as_smi);
|
||||
Label not_smi;
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
__ testl(EAX, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
|
||||
__ movl(EAX, Immediate(Smi::RawValue(kSmiCid)));
|
||||
__ ret();
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(EAX, EAX);
|
||||
__ SmiTag(EAX);
|
||||
__ ret();
|
||||
__ int3();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1445,7 +1445,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Preserve return address, since RA is needed for subroutine call.
|
||||
__ mov(T2, RA);
|
||||
// Loop that checks if there is an IC data match.
|
||||
Label loop, update, test, found, get_class_id_as_smi;
|
||||
Label loop, update, test, found;
|
||||
// S5: IC data object (preserved).
|
||||
__ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
|
||||
// T0: ic_data_array with check entries: classes and target functions.
|
||||
@@ -1459,8 +1459,9 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ subu(T1, T1, TMP);
|
||||
__ sll(T3, T1, 1); // T1 (argument_count - 1) is smi.
|
||||
__ addu(T3, T3, SP);
|
||||
__ bal(&get_class_id_as_smi);
|
||||
__ delay_slot()->lw(T3, Address(T3));
|
||||
__ lw(T3, Address(T3));
|
||||
__ LoadTaggedClassIdMayBeSmi(T3, T3);
|
||||
|
||||
// T1: argument_count - 1 (smi).
|
||||
// T3: receiver's class ID (smi).
|
||||
__ b(&test);
|
||||
@@ -1474,8 +1475,8 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ addu(T3, T1, T3);
|
||||
__ sll(T3, T3, 1);
|
||||
__ addu(T3, SP, T3);
|
||||
__ bal(&get_class_id_as_smi);
|
||||
__ delay_slot()->lw(T3, Address(T3));
|
||||
__ lw(T3, Address(T3));
|
||||
__ LoadTaggedClassIdMayBeSmi(T3, T3);
|
||||
// T3: next argument class ID (smi).
|
||||
__ lw(T4, Address(T0, i * kWordSize));
|
||||
// T4: next class ID to check (smi).
|
||||
@@ -1496,8 +1497,8 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
if (num_args > 1) {
|
||||
__ sll(T3, T1, 1);
|
||||
__ addu(T3, T3, SP);
|
||||
__ bal(&get_class_id_as_smi);
|
||||
__ delay_slot()->lw(T3, Address(T3));
|
||||
__ lw(T3, Address(T3));
|
||||
__ LoadTaggedClassIdMayBeSmi(T3, T3);
|
||||
}
|
||||
|
||||
const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
|
||||
@@ -1572,20 +1573,6 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ lw(T4, FieldAddress(T0, Function::instructions_offset()));
|
||||
__ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag);
|
||||
__ jr(T4);
|
||||
|
||||
// Instance in T3, return its class-id in T3 as Smi.
|
||||
__ Bind(&get_class_id_as_smi);
|
||||
Label not_smi;
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
__ andi(CMPRES1, T3, Immediate(kSmiTagMask));
|
||||
__ bne(CMPRES1, ZR, ¬_smi);
|
||||
__ jr(RA);
|
||||
__ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid)));
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(T3, T3);
|
||||
__ jr(RA);
|
||||
__ delay_slot()->SmiTag(T3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1248,7 +1248,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// Load arguments descriptor into R10.
|
||||
__ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
|
||||
// Loop that checks if there is an IC data match.
|
||||
Label loop, update, test, found, get_class_id_as_smi;
|
||||
Label loop, update, test, found;
|
||||
// RBX: IC data object (preserved).
|
||||
__ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
|
||||
// R12: ic_data_array with check entries: classes and target functions.
|
||||
@@ -1259,7 +1259,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// arguments descriptor array and then access the receiver from the stack).
|
||||
__ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
||||
__ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(RAX, RAX);
|
||||
// RAX: receiver's class ID as smi.
|
||||
__ movq(R13, Address(R12, 0)); // First class ID (Smi) to check.
|
||||
__ jmp(&test);
|
||||
@@ -1270,7 +1270,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
// If not the first, load the next argument's class ID.
|
||||
__ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
||||
__ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize));
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(RAX, RAX);
|
||||
// RAX: next argument class ID (smi).
|
||||
__ movq(R13, Address(R12, i * kWordSize));
|
||||
// R13: next class ID to check (smi).
|
||||
@@ -1288,7 +1288,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
if (num_args > 1) {
|
||||
__ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
||||
__ movq(RAX, Address(RSP, RAX, TIMES_4, 0));
|
||||
__ call(&get_class_id_as_smi);
|
||||
__ LoadTaggedClassIdMayBeSmi(RAX, RAX);
|
||||
}
|
||||
|
||||
const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
|
||||
@@ -1343,19 +1343,6 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
__ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
|
||||
__ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
||||
__ jmp(RCX);
|
||||
|
||||
__ Bind(&get_class_id_as_smi);
|
||||
Label not_smi;
|
||||
// Test if Smi -> load Smi class for comparison.
|
||||
__ testq(RAX, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, ¬_smi, Assembler::kNearJump);
|
||||
__ movq(RAX, Immediate(Smi::RawValue(kSmiCid)));
|
||||
__ ret();
|
||||
|
||||
__ Bind(¬_smi);
|
||||
__ LoadClassId(RAX, RAX);
|
||||
__ SmiTag(RAX);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user