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) ...@@ -736,6 +736,10 @@ ExternalReference::ExternalReference(const SCTableReference& table_ref)
: address_(table_ref.address()) {} : 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) { ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
return ExternalReference(Redirect(isolate, return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(Runtime::PerformGC))); FUNCTION_ADDR(Runtime::PerformGC)));
......
...@@ -561,6 +561,7 @@ class ExternalReference BASE_EMBEDDED { ...@@ -561,6 +561,7 @@ class ExternalReference BASE_EMBEDDED {
// pattern. This means that they have to be added to the // pattern. This means that they have to be added to the
// ExternalReferenceTable in serialize.cc manually. // ExternalReferenceTable in serialize.cc manually.
static ExternalReference flush_icache_function(Isolate* isolate);
static ExternalReference perform_gc_function(Isolate* isolate); static ExternalReference perform_gc_function(Isolate* isolate);
static ExternalReference fill_heap_number_with_random_function( static ExternalReference fill_heap_number_with_random_function(
Isolate* isolate); Isolate* isolate);
......
This diff is collapsed.
...@@ -818,6 +818,20 @@ void MacroAssembler::MultiPopReversedFPU(RegList regs) { ...@@ -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, void MacroAssembler::Ext(Register rt,
Register rs, Register rs,
uint16_t pos, uint16_t pos,
...@@ -4605,6 +4619,37 @@ void MacroAssembler::CallCFunctionHelper(Register function, ...@@ -4605,6 +4619,37 @@ void MacroAssembler::CallCFunctionHelper(Register function,
#undef BRANCH_ARGS_CHECK #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, void MacroAssembler::LoadInstanceDescriptors(Register map,
Register descriptors) { Register descriptors) {
lw(descriptors, lw(descriptors,
......
...@@ -577,6 +577,10 @@ class MacroAssembler: public Assembler { ...@@ -577,6 +577,10 @@ class MacroAssembler: public Assembler {
// into register dst. // into register dst.
void LoadFromSafepointRegisterSlot(Register dst, Register src); 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. // MIPS32 R2 instruction macro.
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size); void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ext(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 { ...@@ -1210,6 +1214,11 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type); void EnterFrame(StackFrame::Type type);
void LeaveFrame(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: private:
void CallCFunctionHelper(Register function, void CallCFunctionHelper(Register function,
ExternalReference function_reference, ExternalReference function_reference,
......
...@@ -2560,7 +2560,12 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -2560,7 +2560,12 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
? CALL_AS_FUNCTION ? CALL_AS_FUNCTION
: CALL_AS_METHOD; : CALL_AS_METHOD;
if (V8::UseCrankshaft()) { 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 { } else {
__ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET,
JUMP_FUNCTION, call_kind); JUMP_FUNCTION, call_kind);
...@@ -3837,7 +3842,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3837,7 +3842,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
// Check that the index is in range. // Check that the index is in range.
__ SmiUntag(t0, key);
__ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset));
// Unsigned comparison catches both negative and too-large values. // Unsigned comparison catches both negative and too-large values.
__ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1)); __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1));
...@@ -3845,7 +3849,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3845,7 +3849,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// Handle both smis and HeapNumbers in the fast path. Go to the // Handle both smis and HeapNumbers in the fast path. Go to the
// runtime for all other kinds of values. // runtime for all other kinds of values.
// a3: external array. // a3: external array.
// t0: key (integer).
if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
// Double to pixel conversion is only implemented in the runtime for now. // Double to pixel conversion is only implemented in the runtime for now.
...@@ -3857,7 +3860,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3857,7 +3860,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
// a3: base pointer of external storage. // a3: base pointer of external storage.
// t0: key (integer).
// t1: value (integer). // t1: value (integer).
switch (elements_kind) { switch (elements_kind) {
...@@ -3874,33 +3876,36 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3874,33 +3876,36 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ mov(v0, t1); // Value is in range 0..255. __ mov(v0, t1); // Value is in range 0..255.
__ bind(&done); __ bind(&done);
__ mov(t1, v0); __ mov(t1, v0);
__ addu(t8, a3, t0);
__ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t1, MemOperand(t8, 0)); __ sb(t1, MemOperand(t8, 0));
} }
break; break;
case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0); __ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t1, MemOperand(t8, 0)); __ sb(t1, MemOperand(t8, 0));
break; break;
case EXTERNAL_SHORT_ELEMENTS: case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1); __ addu(t8, a3, key);
__ addu(t8, a3, t8);
__ sh(t1, MemOperand(t8, 0)); __ sh(t1, MemOperand(t8, 0));
break; break;
case EXTERNAL_INT_ELEMENTS: case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS: case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2); __ sll(t8, key, 1);
__ addu(t8, a3, t8); __ addu(t8, a3, t8);
__ sw(t1, MemOperand(t8, 0)); __ sw(t1, MemOperand(t8, 0));
break; break;
case EXTERNAL_FLOAT_ELEMENTS: case EXTERNAL_FLOAT_ELEMENTS:
// Perform int-to-float conversion and store to memory. // Perform int-to-float conversion and store to memory.
__ SmiUntag(t0, key);
StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4);
break; break;
case EXTERNAL_DOUBLE_ELEMENTS: case EXTERNAL_DOUBLE_ELEMENTS:
__ sll(t8, t0, 3); __ sll(t8, key, 2);
__ addu(a3, a3, t8); __ addu(a3, a3, t8);
// a3: effective address of the double element // a3: effective address of the double element
FloatingPointHelper::Destination destination; FloatingPointHelper::Destination destination;
...@@ -3930,12 +3935,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3930,12 +3935,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
} }
// Entry registers are intact, a0 holds the value which is the return value. // Entry registers are intact, a0 holds the value which is the return value.
__ mov(v0, value); __ mov(v0, a0);
__ Ret(); __ Ret();
if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
// a3: external array. // a3: external array.
// t0: index (integer).
__ bind(&check_heap_number); __ bind(&check_heap_number);
__ GetObjectType(value, t1, t2); __ GetObjectType(value, t1, t2);
__ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE));
...@@ -3943,7 +3947,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3943,7 +3947,6 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
// a3: base pointer of external storage. // a3: base pointer of external storage.
// t0: key (integer).
// The WebGL specification leaves the behavior of storing NaN and // The WebGL specification leaves the behavior of storing NaN and
// +/-Infinity into integer arrays basically undefined. For more // +/-Infinity into integer arrays basically undefined. For more
...@@ -3956,11 +3959,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3956,11 +3959,11 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ cvt_s_d(f0, f0); __ cvt_s_d(f0, f0);
__ sll(t8, t0, 2); __ sll(t8, key, 1);
__ addu(t8, a3, t8); __ addu(t8, a3, t8);
__ swc1(f0, MemOperand(t8, 0)); __ swc1(f0, MemOperand(t8, 0));
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
__ sll(t8, t0, 3); __ sll(t8, key, 2);
__ addu(t8, a3, t8); __ addu(t8, a3, t8);
__ sdc1(f0, MemOperand(t8, 0)); __ sdc1(f0, MemOperand(t8, 0));
} else { } else {
...@@ -3969,18 +3972,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3969,18 +3972,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
switch (elements_kind) { switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0); __ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t3, MemOperand(t8, 0)); __ sb(t3, MemOperand(t8, 0));
break; break;
case EXTERNAL_SHORT_ELEMENTS: case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1); __ addu(t8, a3, key);
__ addu(t8, a3, t8);
__ sh(t3, MemOperand(t8, 0)); __ sh(t3, MemOperand(t8, 0));
break; break;
case EXTERNAL_INT_ELEMENTS: case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS: case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2); __ sll(t8, key, 1);
__ addu(t8, a3, t8); __ addu(t8, a3, t8);
__ sw(t3, MemOperand(t8, 0)); __ sw(t3, MemOperand(t8, 0));
break; break;
...@@ -3998,7 +4001,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -3998,7 +4001,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// Entry registers are intact, a0 holds the value // Entry registers are intact, a0 holds the value
// which is the return value. // which is the return value.
__ mov(v0, value); __ mov(v0, a0);
__ Ret(); __ Ret();
} else { } else {
// FPU is not available, do manual conversions. // FPU is not available, do manual conversions.
...@@ -4053,13 +4056,13 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -4053,13 +4056,13 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
__ or_(t3, t7, t6); __ or_(t3, t7, t6);
__ bind(&done); __ bind(&done);
__ sll(t9, a1, 2); __ sll(t9, key, 1);
__ addu(t9, a2, t9); __ addu(t9, a2, t9);
__ sw(t3, MemOperand(t9, 0)); __ sw(t3, MemOperand(t9, 0));
// Entry registers are intact, a0 holds the value which is the return // Entry registers are intact, a0 holds the value which is the return
// value. // value.
__ mov(v0, value); __ mov(v0, a0);
__ Ret(); __ Ret();
__ bind(&nan_or_infinity_or_zero); __ bind(&nan_or_infinity_or_zero);
...@@ -4077,6 +4080,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -4077,6 +4080,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// t8: effective address of destination element. // t8: effective address of destination element.
__ sw(t4, MemOperand(t8, 0)); __ sw(t4, MemOperand(t8, 0));
__ sw(t3, MemOperand(t8, Register::kSizeInBytes)); __ sw(t3, MemOperand(t8, Register::kSizeInBytes));
__ mov(v0, a0);
__ Ret(); __ Ret();
} else { } else {
bool is_signed_type = IsElementTypeSigned(elements_kind); bool is_signed_type = IsElementTypeSigned(elements_kind);
...@@ -4139,18 +4143,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( ...@@ -4139,18 +4143,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
switch (elements_kind) { switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
__ addu(t8, a3, t0); __ srl(t8, key, 1);
__ addu(t8, a3, t8);
__ sb(t3, MemOperand(t8, 0)); __ sb(t3, MemOperand(t8, 0));
break; break;
case EXTERNAL_SHORT_ELEMENTS: case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
__ sll(t8, t0, 1); __ addu(t8, a3, key);
__ addu(t8, a3, t8);
__ sh(t3, MemOperand(t8, 0)); __ sh(t3, MemOperand(t8, 0));
break; break;
case EXTERNAL_INT_ELEMENTS: case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS: case EXTERNAL_UNSIGNED_INT_ELEMENTS:
__ sll(t8, t0, 2); __ sll(t8, key, 1);
__ addu(t8, a3, t8); __ addu(t8, a3, t8);
__ sw(t3, MemOperand(t8, 0)); __ sw(t3, MemOperand(t8, 0));
break; 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