Commit f19fb455 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

MIPS: Minor fixes to simulator and builtins-mips.

Updated to include fixes to several mips arch-specific files, corresponding to recent changes in r7944, r7935, r7926, r7914, r7910, r7895, and parts of r7423, which had previously been missed for mips. Rebased on r7964.

The simulator changes were missed on r7893 for code-stubs-mips,
where the DirectCEntry stuff was added.

There are also a couple small changes to builtins-mips following
r7879 for the other architectures.

BUG=
TEST=

Review URL: http://codereview.chromium.org//7042031

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7977 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8ea947e6
......@@ -1202,13 +1202,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
kSmiTagSize)));
__ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
// Do not transform the receiver for native (shared already in r2).
__ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kScriptOffset));
__ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
__ Branch(&shift_arguments, eq, a2, Operand(a3));
__ lw(a2, FieldMemOperand(a2, Script::kTypeOffset));
__ sra(a2, a2, kSmiTagSize);
__ Branch(&shift_arguments, eq, a2, Operand(Script::TYPE_NATIVE));
// Do not transform the receiver for native (Compilerhints already in a3).
__ And(t0, a3, Operand(1 << (SharedFunctionInfo::kES5Native +
kSmiTagSize)));
__ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
// Compute the receiver in non-strict mode.
// Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
......@@ -1220,7 +1217,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// a2: first argument
__ JumpIfSmi(a2, &convert_to_object, t2);
// Heap::kUndefinedValueRootIndex is already in a3.
__ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
__ Branch(&use_global_receiver, eq, a2, Operand(a3));
__ LoadRoot(a3, Heap::kNullValueRootIndex);
__ Branch(&use_global_receiver, eq, a2, Operand(a3));
......@@ -1389,20 +1386,17 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
kSmiTagSize)));
__ Branch(&push_receiver, ne, t0, Operand(zero_reg));
// Do not transform the receiver for native (shared already in a1).
__ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kScriptOffset));
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
__ Branch(&push_receiver, eq, a1, Operand(a2));
__ lw(a1, FieldMemOperand(a1, Script::kTypeOffset));
__ sra(a1, a1, kSmiTagSize);
__ Branch(&push_receiver, eq, a1, Operand(Script::TYPE_NATIVE));
// Do not transform the receiver for native (Compilerhints already in a2).
__ And(t0, a2, Operand(1 << (SharedFunctionInfo::kES5Native +
kSmiTagSize)));
__ Branch(&push_receiver, ne, t0, Operand(zero_reg));
// Compute the receiver in non-strict mode.
__ And(t0, a0, Operand(kSmiTagMask));
__ Branch(&call_to_object, eq, t0, Operand(zero_reg));
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ Branch(&use_global_receiver, eq, a0, Operand(a1));
// Heap::kUndefinedValueRootIndex is already in a2.
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
__ Branch(&use_global_receiver, eq, a0, Operand(a2));
// Check if the receiver is already a JavaScript object.
......
......@@ -1472,7 +1472,7 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
scratch1,
Heap::kHeapNumberMapRootIndex,
not_found,
true);
DONT_DO_SMI_CHECK);
STATIC_ASSERT(8 == kDoubleSize);
__ Addu(scratch1,
......@@ -1736,12 +1736,33 @@ void CompareStub::Generate(MacroAssembler* masm) {
// The stub returns zero for false, and a non-zero value for true.
void ToBooleanStub::Generate(MacroAssembler* masm) {
// This stub uses FPU instructions.
ASSERT(CpuFeatures::IsEnabled(FPU));
CpuFeatures::Scope scope(FPU);
Label false_result;
Label not_heap_number;
Register scratch0 = t5.is(tos_) ? t3 : t5;
// undefined -> false
__ LoadRoot(scratch0, Heap::kUndefinedValueRootIndex);
__ Branch(&false_result, eq, tos_, Operand(scratch0));
// Boolean -> its value
__ LoadRoot(scratch0, Heap::kFalseValueRootIndex);
__ Branch(&false_result, eq, tos_, Operand(scratch0));
__ LoadRoot(scratch0, Heap::kTrueValueRootIndex);
// "tos_" is a register and contains a non-zero value. Hence we implicitly
// return true if the equal condition is satisfied.
__ Ret(eq, tos_, Operand(scratch0));
// Smis: 0 -> false, all other -> true
__ And(scratch0, tos_, tos_);
__ Branch(&false_result, eq, scratch0, Operand(zero_reg));
__ And(scratch0, tos_, Operand(kSmiTagMask));
// "tos_" is a register and contains a non-zero value. Hence we implicitly
// return true if the not equal condition is satisfied.
__ Ret(eq, scratch0, Operand(zero_reg));
// 'null' -> false
__ LoadRoot(scratch0, Heap::kNullValueRootIndex);
__ Branch(&false_result, eq, tos_, Operand(scratch0));
......@@ -1750,8 +1771,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
__ Branch(&not_heap_number, ne, scratch0, Operand(at));
__ Subu(at, tos_, Operand(kHeapObjectTag));
__ ldc1(f12, MemOperand(at, HeapNumber::kValueOffset));
__ ldc1(f12, FieldMemOperand(tos_, HeapNumber::kValueOffset));
__ fcmp(f12, 0.0, UEQ);
// "tos_" is a register, and contains a non zero value by default.
......@@ -1762,11 +1782,6 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ bind(&not_heap_number);
// Check if the value is 'null'.
// 'null' => false.
__ LoadRoot(at, Heap::kNullValueRootIndex);
__ Branch(&false_result, eq, tos_, Operand(at));
// It can be an undetectable object.
// Undetectable => false.
__ lw(at, FieldMemOperand(tos_, HeapObject::kMapOffset));
......@@ -1944,12 +1959,14 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
Label non_smi, slow;
GenerateSmiCodeSub(masm, &non_smi, &slow);
Label non_smi, slow, call_builtin;
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
__ bind(&non_smi);
GenerateHeapNumberCodeSub(masm, &slow);
__ bind(&slow);
GenerateTypeTransition(masm);
__ bind(&call_builtin);
GenerateGenericCodeFallback(masm);
}
......@@ -3185,7 +3202,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
a1,
Heap::kHeapNumberMapRootIndex,
&calculate,
true);
DONT_DO_SMI_CHECK);
// Input is a HeapNumber. Store the
// low and high words into a2, a3.
__ lw(a2, FieldMemOperand(a0, HeapNumber::kValueOffset));
......@@ -3764,16 +3781,21 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
#ifdef ENABLE_LOGGING_AND_PROFILING
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address,
masm->isolate());
__ li(t1, Operand(ExternalReference(js_entry_sp)));
__ lw(t2, MemOperand(t1));
{
Label skip;
__ Branch(&skip, ne, t2, Operand(zero_reg));
__ sw(fp, MemOperand(t1));
__ bind(&skip);
}
__ Branch(&non_outermost_js, ne, t2, Operand(zero_reg));
__ sw(fp, MemOperand(t1));
__ li(t0, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
Label cont;
__ b(&cont);
__ nop(); // Branch delay slot nop.
__ bind(&non_outermost_js);
__ li(t0, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
__ bind(&cont);
__ push(t0);
#endif
// Call a faked try-block that does the invoke.
......@@ -3839,32 +3861,21 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
__ Call(t9);
// Unlink this frame from the handler chain. When reading the
// address of the next handler, there is no need to use the address
// displacement since the current stack pointer (sp) points directly
// to the stack handler.
__ lw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
__ li(t0, Operand(ExternalReference(Isolate::k_handler_address,
masm->isolate())));
__ sw(t1, MemOperand(t0));
// Unlink this frame from the handler chain.
__ PopTryHandler();
// This restores sp to its position before PushTryHandler.
__ addiu(sp, sp, StackHandlerConstants::kSize);
#ifdef ENABLE_LOGGING_AND_PROFILING
// If current FP value is the same as js_entry_sp value, it means that
// the current function is the outermost.
__ li(t1, Operand(ExternalReference(js_entry_sp)));
__ lw(t2, MemOperand(t1));
{
Label skip;
__ Branch(&skip, ne, fp, Operand(t2));
__ bind(&exit); // v0 holds result
#ifdef ENABLE_LOGGING_AND_PROFILING
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(t1);
__ Branch(&non_outermost_js_2, ne, t1,
Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
__ li(t1, Operand(ExternalReference(js_entry_sp)));
__ sw(zero_reg, MemOperand(t1));
__ bind(&skip);
}
#endif
__ bind(&non_outermost_js_2);
#endif
__ bind(&exit); // v0 holds result.
// Restore the top frame descriptors from the stack.
__ pop(t1);
__ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address,
......@@ -4846,7 +4857,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
scratch_,
Heap::kHeapNumberMapRootIndex,
index_not_number_,
true);
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
// Consumed by runtime conversion function:
__ Push(object_, index_, index_);
......
......@@ -566,19 +566,6 @@ void FullCodeGenerator::DoTest(Label* if_true,
Label* if_false,
Label* fall_through) {
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Emit the inlined tests assumed by the stub.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(if_false, eq, result_register(), Operand(at));
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(if_true, eq, result_register(), Operand(at));
__ LoadRoot(at, Heap::kFalseValueRootIndex);
__ Branch(if_false, eq, result_register(), Operand(at));
STATIC_ASSERT(kSmiTag == 0);
__ Branch(if_false, eq, result_register(), Operand(zero_reg));
__ JumpIfSmi(result_register(), if_true);
// Call the ToBoolean stub for all other cases.
ToBooleanStub stub(result_register());
__ CallStub(&stub);
__ mov(at, zero_reg);
......@@ -589,8 +576,6 @@ void FullCodeGenerator::DoTest(Label* if_true,
__ CallRuntime(Runtime::kToBool, 1);
__ LoadRoot(at, Heap::kFalseValueRootIndex);
}
// The stub returns nonzero for true.
Split(ne, v0, Operand(at), if_true, if_false, fall_through);
}
......
......@@ -874,10 +874,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
}
Object* KeyedLoadIC_Miss(Arguments args);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
// ---------- S t a t e --------------
// -- ra : return address
// -- a0 : key
......@@ -889,8 +886,11 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
__ Push(a1, a0);
ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss),
isolate);
// Perform tail call to the entry.
ExternalReference ref = force_generic
? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric), isolate)
: ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
__ TailCallExternalReference(ref, 2, 1);
}
......@@ -1097,7 +1097,7 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
char_at_generator.GenerateSlow(masm, call_helper);
__ bind(&miss);
GenerateMiss(masm);
GenerateMiss(masm, false);
}
......@@ -1263,11 +1263,30 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
IC_Utility(kKeyedLoadPropertyWithInterceptor), masm->isolate()), 2, 1);
__ bind(&slow);
GenerateMiss(masm);
GenerateMiss(masm, false);
}
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
// ---------- S t a t e --------------
// -- a0 : value
// -- a1 : key
// -- a2 : receiver
// -- ra : return address
// -----------------------------------
// Push receiver, key and value for runtime call.
__ Push(a2, a1, a0);
ExternalReference ref = force_generic
? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
masm->isolate())
: ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
__ TailCallExternalReference(ref, 3, 1);
}
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- a0 : value
// -- a1 : key
......@@ -1279,8 +1298,11 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
// We can't use MultiPush as the order of the registers is important.
__ Push(a2, a1, a0);
ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss),
masm->isolate());
// The slow case calls into the runtime to complete the store without causing
// an IC miss that would otherwise cause a transition to the generic stub.
ExternalReference ref =
ExternalReference(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
__ TailCallExternalReference(ref, 3, 1);
}
......
......@@ -2545,8 +2545,8 @@ void MacroAssembler::CheckMap(Register obj,
Register scratch,
Handle<Map> map,
Label* fail,
bool is_heap_object) {
if (!is_heap_object) {
SmiCheckType smi_check_type) {
if (smi_check_type == DO_SMI_CHECK) {
JumpIfSmi(obj, fail);
}
lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
......@@ -2555,12 +2555,27 @@ void MacroAssembler::CheckMap(Register obj,
}
void MacroAssembler::DispatchMap(Register obj,
Register scratch,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type) {
Label fail;
if (smi_check_type == DO_SMI_CHECK) {
JumpIfSmi(obj, &fail);
}
lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map));
bind(&fail);
}
void MacroAssembler::CheckMap(Register obj,
Register scratch,
Heap::RootListIndex index,
Label* fail,
bool is_heap_object) {
if (!is_heap_object) {
SmiCheckType smi_check_type) {
if (smi_check_type == DO_SMI_CHECK) {
JumpIfSmi(obj, fail);
}
lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
......@@ -2860,7 +2875,7 @@ MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub,
{ MaybeObject* maybe_result = stub->TryGetCode();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2);
Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2);
return result;
}
......@@ -3410,7 +3425,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
if (emit_debug_code()) {
Label ok, fail;
CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
Branch(&ok);
bind(&fail);
Abort("Global functions must have initial map");
......
......@@ -30,6 +30,7 @@
#include "assembler.h"
#include "mips/assembler-mips.h"
#include "v8globals.h"
namespace v8 {
namespace internal {
......@@ -710,13 +711,22 @@ DECLARE_NOTARGET_PROTOTYPE(Ret)
Register scratch,
Handle<Map> map,
Label* fail,
bool is_heap_object);
SmiCheckType smi_check_type);
void CheckMap(Register obj,
Register scratch,
Heap::RootListIndex index,
Label* fail,
bool is_heap_object);
SmiCheckType smi_check_type);
// Check if the map of an object is equal to a specified map and branch to a
// specified target if equal. Skip the smi check if not required (object is
// known to be a heap object)
void DispatchMap(Register obj,
Register scratch,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type);
// Generates code for reporting that an illegal operation has
// occurred.
......
......@@ -1165,7 +1165,11 @@ typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
// This signature supports direct call in to API function native callback
// (refer to InvocationCallback in v8.h).
typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0);
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
// This signature supports direct call to accessor getter callback.
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
int32_t arg1);
// Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime. They are also used for debugging with simulator.
......@@ -1240,15 +1244,27 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
set_register(v0, gpreg_pair[0]);
set_register(v1, gpreg_pair[1]);
} else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
SimulatorRuntimeApiCall target =
reinterpret_cast<SimulatorRuntimeApiCall>(external);
// See DirectCEntryStub::GenerateCall for explanation of register usage.
SimulatorRuntimeDirectApiCall target =
reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
if (::v8::internal::FLAG_trace_sim) {
PrintF("Call to host function at %p args %08x\n",
FUNCTION_ADDR(target),
arg0);
FUNCTION_ADDR(target), arg1);
}
v8::Handle<v8::Value> result = target(arg1);
*(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
set_register(v0, arg0);
} else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
// See DirectCEntryStub::GenerateCall for explanation of register usage.
SimulatorRuntimeDirectGetterCall target =
reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
if (::v8::internal::FLAG_trace_sim) {
PrintF("Call to host function at %p args %08x %08x\n",
FUNCTION_ADDR(target), arg1, arg2);
}
v8::Handle<v8::Value> result = target(arg0);
set_register(v0, (int32_t) *result);
v8::Handle<v8::Value> result = target(arg1, arg2);
*(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
set_register(v0, arg0);
} else {
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
......
......@@ -50,7 +50,7 @@ namespace internal {
entry(p0, p1, p2, p3, p4)
typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
int*, Address, int, Isolate*);
void*, int*, Address, int, Isolate*);
// Call the generated regexp code directly. The code at the entry address
......@@ -58,7 +58,8 @@ typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
// The fifth argument is a dummy that reserves the space used for
// the return address added by the ExitFrame in native calls.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
(FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7))
(FUNCTION_CAST<mips_regexp_matcher>(entry)( \
p0, p1, p2, p3, NULL, p4, p5, p6, p7))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
......@@ -361,7 +362,7 @@ class Simulator {
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
Simulator::current(Isolate::Current())->Call( \
entry, 8, p0, p1, p2, p3, p4, p5, p6, p7)
entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
......
This diff is collapsed.
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