Commit c74aae24 authored by danno@chromium.org's avatar danno@chromium.org

MIPS: pre-crankshaft updates to code-stubs and stub-cache (3/3)

Highlights:
- code-stubs-mips.cc
-- use EmitFPUTruncate in place of inline code in several places.
-- use BranchF macro rather than lower-level FP cmp and branch for readability.
-- Port of Sven's r8859 (Implement type recording for ToBoolean) and r8886
(Simplify and optimize ToBoolean handling.)
-- Fix bug in TranscendentalCacheStub::Generate where some regs were not
saved across CFunction call.
-- use updated xxxCFunction macros.
-- update InstanceOfStub to support crankshaft
DoDeferredLInstanceOfKnownGlobal
-- Provide code-patching and I-cache flushing support for generated
code, used for InstanceOfStub under crankshaft (not submitted here).
This requires adding new ExternalReference to src/assember.cc,h

- stub-cache-mips.cc
-- port Danno's r8901 (Create a common base class for Fixed-, FixedDouble-
and ExternalArrays) to mips crankshaft branch.

BUG=
TEST=

Review URL: http://codereview.chromium.org/7890001
Patch from Paul Lind <plind44@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9308 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c579bfe6
......@@ -736,6 +736,10 @@ ExternalReference::ExternalReference(const SCTableReference& table_ref)
: address_(table_ref.address()) {}
ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(CPU::FlushICache)));
}
ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(Runtime::PerformGC)));
......
......@@ -561,6 +561,7 @@ class ExternalReference BASE_EMBEDDED {
// pattern. This means that they have to be added to the
// ExternalReferenceTable in serialize.cc manually.
static ExternalReference flush_icache_function(Isolate* isolate);
static ExternalReference perform_gc_function(Isolate* isolate);
static ExternalReference fill_heap_number_with_random_function(
Isolate* isolate);
......
This diff is collapsed.
......@@ -818,6 +818,20 @@ void MacroAssembler::MultiPopReversedFPU(RegList regs) {
}
void MacroAssembler::FlushICache(Register address, unsigned instructions) {
RegList saved_regs = kJSCallerSaved | ra.bit();
MultiPush(saved_regs);
// Save to a0 in case address == t0.
Move(a0, address);
PrepareCallCFunction(2, t0);
li(a1, instructions * kInstrSize);
CallCFunction(ExternalReference::flush_icache_function(isolate()), 2);
MultiPop(saved_regs);
}
void MacroAssembler::Ext(Register rt,
Register rs,
uint16_t pos,
......@@ -4605,6 +4619,37 @@ void MacroAssembler::CallCFunctionHelper(Register function,
#undef BRANCH_ARGS_CHECK
void MacroAssembler::PatchRelocatedValue(Register li_location,
Register scratch,
Register new_value) {
lw(scratch, MemOperand(li_location));
// At this point scratch is a lui(at, ...) instruction.
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
Check(eq, "The instruction to patch should be a lui.",
scratch, Operand(LUI));
lw(scratch, MemOperand(li_location));
}
srl(t9, new_value, kImm16Bits);
Ins(scratch, t9, 0, kImm16Bits);
sw(scratch, MemOperand(li_location));
lw(scratch, MemOperand(li_location, kInstrSize));
// scratch is now ori(at, ...).
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
Check(eq, "The instruction to patch should be an ori.",
scratch, Operand(ORI));
lw(scratch, MemOperand(li_location, kInstrSize));
}
Ins(scratch, new_value, 0, kImm16Bits);
sw(scratch, MemOperand(li_location, kInstrSize));
// Update the I-cache so the new lui and ori can be executed.
FlushICache(li_location, 2);
}
void MacroAssembler::LoadInstanceDescriptors(Register map,
Register descriptors) {
lw(descriptors,
......
......@@ -577,6 +577,10 @@ class MacroAssembler: public Assembler {
// into register dst.
void LoadFromSafepointRegisterSlot(Register dst, Register src);
// Flush the I-cache from asm code. You should use CPU::FlushICache from C.
// Does not handle errors.
void FlushICache(Register address, unsigned instructions);
// MIPS32 R2 instruction macro.
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
......@@ -1210,6 +1214,11 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
// Patch the relocated value (lui/ori pair).
void PatchRelocatedValue(Register li_location,
Register scratch,
Register new_value);
private:
void CallCFunctionHelper(Register function,
ExternalReference function_reference,
......
......@@ -2560,7 +2560,12 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
if (V8::UseCrankshaft()) {
UNIMPLEMENTED_MIPS();
// TODO(kasperl): For now, we always call indirectly through the
// code field in the function to allow recompilation to take effect
// without changing any of the call sites.
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
} else {
__ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET,
JUMP_FUNCTION, call_kind);
......@@ -3837,7 +3842,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
// Check that the index is in range.
__ SmiUntag(t0, key);
__ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset));
// Unsigned comparison catches both negative and too-large values.
__ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1));
......@@ -3845,7 +3849,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// Handle both smis and HeapNumbers in the fast path. Go to the
// runtime for all other kinds of values.
// a3: external array.
// t0: key (integer).
if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
// Double to pixel conversion is only implemented in the runtime for now.
......@@ -3857,7 +3860,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
// a3: base pointer of external storage.
// t0: key (integer).
// t1: value (integer).
switch (elements_kind) {
......@@ -3874,33 +3876,36 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ mov(v0, t1); // Value is in range 0..255.
__ bind(&done);
__ mov(t1, v0);
__ addu(t8, a3, t0);
__ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t1, MemOperand(t8, 0));
}
break;
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0);
__ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t1, MemOperand(t8, 0));
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1);
__ addu(t8, a3, t8);
__ addu(t8, a3, key);
__ sh(t1, MemOperand(t8, 0));
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2);
__ sll(t8, key, 1);
__ addu(t8, a3, t8);
__ sw(t1, MemOperand(t8, 0));
break;
case EXTERNAL_FLOAT_ELEMENTS:
// Perform int-to-float conversion and store to memory.
__ SmiUntag(t0, key);
StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4);
break;
case EXTERNAL_DOUBLE_ELEMENTS:
__ sll(t8, t0, 3);
__ sll(t8, key, 2);
__ addu(a3, a3, t8);
// a3: effective address of the double element
FloatingPointHelper::Destination destination;
......@@ -3930,12 +3935,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
}
// Entry registers are intact, a0 holds the value which is the return value.
__ mov(v0, value);
__ mov(v0, a0);
__ Ret();
if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
// a3: external array.
// t0: index (integer).
__ bind(&check_heap_number);
__ GetObjectType(value, t1, t2);
__ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE));
......@@ -3943,7 +3947,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
// a3: base pointer of external storage.
// t0: key (integer).
// The WebGL specification leaves the behavior of storing NaN and
// +/-Infinity into integer arrays basically undefined. For more
......@@ -3956,11 +3959,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ cvt_s_d(f0, f0);
__ sll(t8, t0, 2);
__ sll(t8, key, 1);
__ addu(t8, a3, t8);
__ swc1(f0, MemOperand(t8, 0));
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
__ sll(t8, t0, 3);
__ sll(t8, key, 2);
__ addu(t8, a3, t8);
__ sdc1(f0, MemOperand(t8, 0));
} else {
......@@ -3969,18 +3972,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0);
__ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t3, MemOperand(t8, 0));
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1);
__ addu(t8, a3, t8);
__ addu(t8, a3, key);
__ sh(t3, MemOperand(t8, 0));
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2);
__ sll(t8, key, 1);
__ addu(t8, a3, t8);
__ sw(t3, MemOperand(t8, 0));
break;
......@@ -3998,7 +4001,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// Entry registers are intact, a0 holds the value
// which is the return value.
__ mov(v0, value);
__ mov(v0, a0);
__ Ret();
} else {
// FPU is not available, do manual conversions.
......@@ -4053,13 +4056,13 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ or_(t3, t7, t6);
__ bind(&done);
__ sll(t9, a1, 2);
__ sll(t9, key, 1);
__ addu(t9, a2, t9);
__ sw(t3, MemOperand(t9, 0));
// Entry registers are intact, a0 holds the value which is the return
// value.
__ mov(v0, value);
__ mov(v0, a0);
__ Ret();
__ bind(&nan_or_infinity_or_zero);
......@@ -4077,6 +4080,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// t8: effective address of destination element.
__ sw(t4, MemOperand(t8, 0));
__ sw(t3, MemOperand(t8, Register::kSizeInBytes));
__ mov(v0, a0);
__ Ret();
} else {
bool is_signed_type = IsElementTypeSigned(elements_kind);
......@@ -4139,18 +4143,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0);
__ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t3, MemOperand(t8, 0));
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1);
__ addu(t8, a3, t8);
__ addu(t8, a3, key);
__ sh(t3, MemOperand(t8, 0));
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2);
__ sll(t8, key, 1);
__ addu(t8, a3, t8);
__ sw(t3, MemOperand(t8, 0));
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment