mirror of
https://github.com/dart-lang/sdk
synced 2024-10-05 17:35:02 +00:00
Adds native/leaf runtime call stub and redirection on MIPS.
Review URL: https://codereview.chromium.org//13473010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@20813 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
c3777f14fd
commit
3e080d1b34
|
@ -70,13 +70,9 @@ dart/*: Skip
|
|||
|
||||
[ $arch == simmips ]
|
||||
# Tests needing an assembler.
|
||||
cc/CallLeafRuntimeStubCode: Skip
|
||||
cc/CallRuntimeStubCode: Skip
|
||||
cc/Dart2JSCompileAll: Skip
|
||||
cc/FrameLookup: Skip
|
||||
cc/IcDataAccess: Skip
|
||||
cc/Jump: Skip
|
||||
cc/PatchStaticCall: Skip
|
||||
cc/UseDartApi: Skip
|
||||
# Tests needing Dart execution.
|
||||
dart/*: Skip
|
||||
|
|
|
@ -515,6 +515,15 @@ class Assembler : public ValueObject {
|
|||
jr(TMP);
|
||||
}
|
||||
|
||||
void BranchPatchable(const ExternalLabel* label) {
|
||||
const uint16_t low = Utils::Low16Bits(label->address());
|
||||
const uint16_t high = Utils::High16Bits(label->address());
|
||||
lui(TMP, Immediate(high));
|
||||
ori(TMP, TMP, Immediate(low));
|
||||
jr(TMP);
|
||||
delay_slot()->nop();
|
||||
}
|
||||
|
||||
void BranchLink(const ExternalLabel* label) {
|
||||
LoadImmediate(TMP, label->address());
|
||||
jalr(TMP);
|
||||
|
@ -525,6 +534,7 @@ class Assembler : public ValueObject {
|
|||
Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag;
|
||||
LoadWordFromPoolOffset(TMP, offset);
|
||||
jalr(TMP);
|
||||
delay_slot()->nop();
|
||||
}
|
||||
|
||||
// If the signed value in rs is less than value, rd is 1, and 0 otherwise.
|
||||
|
|
|
@ -252,6 +252,7 @@ void FlowGraphCompiler::EmitFrameEntry() {
|
|||
__ EnterDartFrame((StackSize() * kWordSize));
|
||||
}
|
||||
|
||||
|
||||
// Input parameters:
|
||||
// RA: return address.
|
||||
// SP: address of last argument.
|
||||
|
@ -404,7 +405,9 @@ void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
|
|||
const ExternalLabel* label,
|
||||
PcDescriptors::Kind kind,
|
||||
LocationSummary* locs) {
|
||||
UNIMPLEMENTED();
|
||||
__ BranchLinkPatchable(label);
|
||||
AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
|
||||
RecordSafepoint(locs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -162,19 +162,37 @@ JumpPattern::JumpPattern(uword pc) : pc_(pc) { }
|
|||
|
||||
|
||||
bool JumpPattern::IsValid() const {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
|
||||
Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
|
||||
Instr* jr = Instr::At(pc_ + (2 * Instr::kInstrSize));
|
||||
Instr* nop = Instr::At(pc_ + (3 * Instr::kInstrSize));
|
||||
return (lui->OpcodeField() == LUI) &&
|
||||
(ori->OpcodeField() == ORI) &&
|
||||
(jr->OpcodeField() == SPECIAL) &&
|
||||
(jr->FunctionField() == JR) &&
|
||||
(nop->InstructionBits() == Instr::kNopInstruction);
|
||||
}
|
||||
|
||||
|
||||
uword JumpPattern::TargetAddress() const {
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
|
||||
Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
|
||||
const uint16_t target_lo = ori->UImmField();
|
||||
const uint16_t target_hi = lui->UImmField();
|
||||
return (target_hi << 16) | target_lo;
|
||||
}
|
||||
|
||||
|
||||
void JumpPattern::SetTargetAddress(uword target_address) const {
|
||||
UNIMPLEMENTED();
|
||||
Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
|
||||
Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
|
||||
const int32_t lui_bits = lui->InstructionBits();
|
||||
const int32_t ori_bits = ori->InstructionBits();
|
||||
const uint16_t target_lo = target_address & 0xffff;
|
||||
const uint16_t target_hi = target_address >> 16;
|
||||
|
||||
lui->SetInstructionBits((lui_bits & 0xffff0000) | target_hi);
|
||||
ori->SetInstructionBits((ori_bits & 0xffff0000) | target_lo);
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -46,7 +46,8 @@ class JumpPattern : public ValueObject {
|
|||
public:
|
||||
explicit JumpPattern(uword pc);
|
||||
|
||||
static const int kLengthInBytes = 3*Instr::kInstrSize;
|
||||
// lui; ori; jr; nop (in delay slot) = 4.
|
||||
static const int kLengthInBytes = 4*Instr::kInstrSize;
|
||||
|
||||
int pattern_length_in_bytes() const {
|
||||
return kLengthInBytes;
|
||||
|
|
|
@ -33,7 +33,8 @@ ASSEMBLER_TEST_RUN(Call, test) {
|
|||
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Jump, assembler) {
|
||||
UNIMPLEMENTED();
|
||||
__ BranchPatchable(&StubCode::InstanceFunctionLookupLabel());
|
||||
__ BranchPatchable(&StubCode::AllocateArrayLabel());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -197,13 +197,47 @@ void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
|
||||
|
||||
LocationSummary* NativeCallInstr::MakeLocationSummary() const {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
const intptr_t kNumInputs = 0;
|
||||
const intptr_t kNumTemps = 3;
|
||||
LocationSummary* locs =
|
||||
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
||||
locs->set_temp(0, Location::RegisterLocation(A1));
|
||||
locs->set_temp(1, Location::RegisterLocation(A2));
|
||||
locs->set_temp(2, Location::RegisterLocation(T5));
|
||||
locs->set_out(Location::RegisterLocation(V0));
|
||||
return locs;
|
||||
}
|
||||
|
||||
|
||||
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
UNIMPLEMENTED();
|
||||
ASSERT(locs()->temp(0).reg() == A1);
|
||||
ASSERT(locs()->temp(1).reg() == A2);
|
||||
ASSERT(locs()->temp(2).reg() == T5);
|
||||
Register result = locs()->out().reg();
|
||||
|
||||
// Push the result place holder initialized to NULL.
|
||||
__ PushObject(Object::ZoneHandle());
|
||||
// Pass a pointer to the first argument in A2.
|
||||
if (!function().HasOptionalParameters()) {
|
||||
__ addiu(A2, FP, Immediate((kLastParamSlotIndex +
|
||||
function().NumParameters() - 1) * kWordSize));
|
||||
} else {
|
||||
__ addiu(A2, FP, Immediate(kFirstLocalSlotIndex * kWordSize));
|
||||
}
|
||||
// Compute the effective address. When running under the simulator,
|
||||
// this is a redirection address that forces the simulator to call
|
||||
// into the runtime system.
|
||||
uword entry = reinterpret_cast<uword>(native_c_function());
|
||||
#if defined(USING_SIMULATOR)
|
||||
entry = Simulator::RedirectExternalReference(entry, Simulator::kNativeCall);
|
||||
#endif
|
||||
__ LoadImmediate(T5, entry);
|
||||
__ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function()));
|
||||
compiler->GenerateCall(token_pos(),
|
||||
&StubCode::CallNativeCFunctionLabel(),
|
||||
PcDescriptors::kOther,
|
||||
locs());
|
||||
__ Pop(result);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -100,8 +100,91 @@ void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Input parameters:
|
||||
// RA : return address.
|
||||
// SP : address of return value.
|
||||
// T5 : address of the native function to call.
|
||||
// A2 : address of first argument in argument array.
|
||||
// A1 : argc_tag including number of arguments and function kind.
|
||||
void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
|
||||
__ Unimplemented("CallNativeCFunction stub");
|
||||
const intptr_t isolate_offset = NativeArguments::isolate_offset();
|
||||
const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
|
||||
const intptr_t argv_offset = NativeArguments::argv_offset();
|
||||
const intptr_t retval_offset = NativeArguments::retval_offset();
|
||||
|
||||
__ addiu(SP, SP, Immediate(-2 * kWordSize));
|
||||
__ sw(RA, Address(SP, 1 * kWordSize));
|
||||
__ sw(FP, Address(SP, 0 * kWordSize));
|
||||
__ mov(FP, SP);
|
||||
|
||||
// Load current Isolate pointer from Context structure into A0.
|
||||
__ lw(A0, FieldAddress(CTX, Context::isolate_offset()));
|
||||
|
||||
// Save exit frame information to enable stack walking as we are about
|
||||
// to transition to native code.
|
||||
__ sw(SP, Address(A0, Isolate::top_exit_frame_info_offset()));
|
||||
|
||||
// Save current Context pointer into Isolate structure.
|
||||
__ sw(CTX, Address(A0, Isolate::top_context_offset()));
|
||||
|
||||
// Cache Isolate pointer into CTX while executing native code.
|
||||
__ mov(CTX, A0);
|
||||
|
||||
// Reserve space for the native arguments structure passed on the stack (the
|
||||
// outgoing pointer parameter to the native arguments structure is passed in
|
||||
// R0) and align frame before entering the C++ world.
|
||||
__ ReserveAlignedFrameSpace(sizeof(NativeArguments));
|
||||
|
||||
// Initialize NativeArguments structure and call native function.
|
||||
// Registers A0, A1, A2, and A3 are used.
|
||||
|
||||
ASSERT(isolate_offset == 0 * kWordSize);
|
||||
// Set isolate in NativeArgs: A0 already contains CTX.
|
||||
|
||||
// There are no native calls to closures, so we do not need to set the tag
|
||||
// bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
|
||||
ASSERT(argc_tag_offset == 1 * kWordSize);
|
||||
// Set argc in NativeArguments: T1 already contains argc.
|
||||
|
||||
ASSERT(argv_offset == 2 * kWordSize);
|
||||
// Set argv in NativeArguments: T2 already contains argv.
|
||||
|
||||
ASSERT(retval_offset == 3 * kWordSize);
|
||||
__ addiu(A3, FP, Immediate(2 * kWordSize)); // Set retval in NativeArgs.
|
||||
|
||||
// TODO(regis): Should we pass the structure by value as in runtime calls?
|
||||
// It would require changing Dart API for native functions.
|
||||
// For now, space is reserved on the stack and we pass a pointer to it.
|
||||
__ addiu(SP, SP, Immediate(-4 * kWordSize));
|
||||
__ sw(A3, Address(SP, 3 * kWordSize));
|
||||
__ sw(A2, Address(SP, 2 * kWordSize));
|
||||
__ sw(A1, Address(SP, 1 * kWordSize));
|
||||
__ sw(A0, Address(SP, 0 * kWordSize));
|
||||
|
||||
__ mov(A0, SP); // Pass the pointer to the NativeArguments.
|
||||
|
||||
// Call native function or redirection via simulator.
|
||||
__ jalr(T5);
|
||||
|
||||
// Reset exit frame information in Isolate structure.
|
||||
__ LoadImmediate(A2, 0);
|
||||
__ sw(A2, Address(CTX, Isolate::top_exit_frame_info_offset()));
|
||||
|
||||
// Load Context pointer from Isolate structure into R2.
|
||||
__ lw(A2, Address(CTX, Isolate::top_context_offset()));
|
||||
|
||||
// Reset Context pointer in Isolate structure.
|
||||
__ LoadImmediate(A3, reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ sw(A3, Address(CTX, Isolate::top_context_offset()));
|
||||
|
||||
// Cache Context pointer into CTX while executing Dart code.
|
||||
__ mov(CTX, A2);
|
||||
|
||||
__ mov(SP, FP);
|
||||
__ lw(RA, Address(SP, 1 * kWordSize));
|
||||
__ lw(FP, Address(SP, 0 * kWordSize));
|
||||
__ addiu(SP, SP, Immediate(2 * kWordSize));
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,23 @@ static Function* CreateFunction(const char* name) {
|
|||
// Test calls to stub code which calls into the runtime.
|
||||
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
|
||||
int value1, int value2) {
|
||||
UNIMPLEMENTED();
|
||||
const int argc = 2;
|
||||
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
|
||||
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
|
||||
const Object& result = Object::ZoneHandle();
|
||||
const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld));
|
||||
ASSERT(context.isolate() == Isolate::Current());
|
||||
__ EnterDartFrame(0);
|
||||
__ LoadObject(CTX, context);
|
||||
__ PushObject(result); // Push Null object for return value.
|
||||
__ PushObject(smi1); // Push argument 1 smi1.
|
||||
__ PushObject(smi2); // Push argument 2 smi2.
|
||||
ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
|
||||
__ CallRuntime(kTestSmiSubRuntimeEntry); // Call SmiSub runtime func.
|
||||
__ addiu(SP, SP, Immediate(argc * kWordSize));
|
||||
__ Pop(V0); // Pop return value from return slot.
|
||||
__ LeaveDartFrame();
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +80,15 @@ TEST_CASE(CallRuntimeStubCode) {
|
|||
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
|
||||
int value1,
|
||||
int value2) {
|
||||
UNIMPLEMENTED();
|
||||
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
|
||||
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
|
||||
__ EnterDartFrame(0);
|
||||
__ ReserveAlignedFrameSpace(0);
|
||||
__ LoadObject(A0, smi1); // Set up argument 1 smi1.
|
||||
__ LoadObject(A1, smi2); // Set up argument 2 smi2.
|
||||
__ CallRuntime(kTestLeafSmiAddRuntimeEntry); // Call SmiAdd runtime func.
|
||||
__ LeaveDartFrame();
|
||||
__ Ret(); // Return value is in R0.
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue