Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h
index b463c0b..57aea38 100644
--- a/src/mips/assembler-mips-inl.h
+++ b/src/mips/assembler-mips-inl.h
@@ -463,6 +463,8 @@
CheckTrampolinePoolQuick();
}
+template <>
+inline void Assembler::EmitHelper(uint8_t x);
template <typename T>
void Assembler::EmitHelper(T x) {
@@ -471,6 +473,14 @@
CheckTrampolinePoolQuick();
}
+template <>
+void Assembler::EmitHelper(uint8_t x) {
+ *reinterpret_cast<uint8_t*>(pc_) = x;
+ pc_ += sizeof(x);
+ if (reinterpret_cast<intptr_t>(pc_) % kInstrSize == 0) {
+ CheckTrampolinePoolQuick();
+ }
+}
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
if (!is_buffer_growth_blocked()) {
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index f95323b..8bda17c 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -194,36 +194,25 @@
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::wasm_global_reference() {
+ DCHECK(IsWasmGlobalReference(rmode_));
+ return Assembler::target_address_at(pc_, host_);
+}
+
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
}
-void RelocInfo::update_wasm_memory_reference(
- Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
- ICacheFlushMode icache_flush_mode) {
- DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
- if (IsWasmMemoryReference(rmode_)) {
- Address updated_memory_reference;
- DCHECK(old_base <= wasm_memory_reference() &&
- wasm_memory_reference() < old_base + old_size);
- updated_memory_reference = new_base + (wasm_memory_reference() - old_base);
- DCHECK(new_base <= updated_memory_reference &&
- updated_memory_reference < new_base + new_size);
- Assembler::set_target_address_at(
- isolate_, pc_, host_, updated_memory_reference, icache_flush_mode);
- } else if (IsWasmMemorySizeReference(rmode_)) {
- uint32_t updated_size_reference;
- DCHECK(wasm_memory_size_reference() <= old_size);
- updated_size_reference =
- new_size + (wasm_memory_size_reference() - old_size);
- DCHECK(updated_size_reference <= new_size);
- Assembler::set_target_address_at(
- isolate_, pc_, host_, reinterpret_cast<Address>(updated_size_reference),
- icache_flush_mode);
- } else {
- UNREACHABLE();
- }
+void RelocInfo::unchecked_update_wasm_memory_reference(
+ Address address, ICacheFlushMode flush_mode) {
+ Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+ ICacheFlushMode flush_mode) {
+ Assembler::set_target_address_at(isolate_, pc_, host_,
+ reinterpret_cast<Address>(size), flush_mode);
}
// -----------------------------------------------------------------------------
@@ -330,6 +319,8 @@
desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
desc->origin = this;
desc->constant_pool_size = 0;
+ desc->unwinding_info_size = 0;
+ desc->unwinding_info = nullptr;
}
@@ -1277,7 +1268,6 @@
void Assembler::bal(int16_t offset) {
- positions_recorder()->WriteRecordedPositions();
bgezal(zero_reg, offset);
}
@@ -1290,7 +1280,6 @@
void Assembler::balc(int32_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
}
@@ -1337,7 +1326,6 @@
void Assembler::bgezal(Register rs, int16_t offset) {
DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
BlockTrampolinePoolScope block_trampoline_pool(this);
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
@@ -1408,7 +1396,6 @@
void Assembler::bltzal(Register rs, int16_t offset) {
DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
BlockTrampolinePoolScope block_trampoline_pool(this);
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
@@ -1444,7 +1431,6 @@
void Assembler::blezalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(BLEZ, zero_reg, rt, offset,
CompactBranchType::COMPACT_BRANCH);
}
@@ -1453,7 +1439,6 @@
void Assembler::bgezalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
}
@@ -1462,7 +1447,6 @@
DCHECK(!IsMipsArchVariant(kMips32r6));
DCHECK(!(rs.is(zero_reg)));
BlockTrampolinePoolScope block_trampoline_pool(this);
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
@@ -1471,7 +1455,6 @@
void Assembler::bltzalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
}
@@ -1479,7 +1462,6 @@
void Assembler::bgtzalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(BGTZ, zero_reg, rt, offset,
CompactBranchType::COMPACT_BRANCH);
}
@@ -1488,7 +1470,6 @@
void Assembler::beqzalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(ADDI, zero_reg, rt, offset,
CompactBranchType::COMPACT_BRANCH);
}
@@ -1497,7 +1478,6 @@
void Assembler::bnezalc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rt.is(zero_reg)));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(DADDI, zero_reg, rt, offset,
CompactBranchType::COMPACT_BRANCH);
}
@@ -1556,9 +1536,6 @@
void Assembler::jr(Register rs) {
if (!IsMipsArchVariant(kMips32r6)) {
BlockTrampolinePoolScope block_trampoline_pool(this);
- if (rs.is(ra)) {
- positions_recorder()->WriteRecordedPositions();
- }
GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
BlockTrampolinePoolFor(1); // For associated delay slot.
} else {
@@ -1576,7 +1553,6 @@
DCHECK(in_range && ((target & 3) == 0));
#endif
BlockTrampolinePoolScope block_trampoline_pool(this);
- positions_recorder()->WriteRecordedPositions();
GenInstrJump(JAL, (target >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
@@ -1585,7 +1561,6 @@
void Assembler::jalr(Register rs, Register rd) {
DCHECK(rs.code() != rd.code());
BlockTrampolinePoolScope block_trampoline_pool(this);
- positions_recorder()->WriteRecordedPositions();
GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
@@ -1599,7 +1574,6 @@
void Assembler::jialc(Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
- positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(POP76, zero_reg, rt, offset);
}
@@ -1940,7 +1914,6 @@
GenInstrImmediate(LUI, rs, rt, j);
}
-
// ---------PC-Relative instructions-----------
void Assembler::addiupc(Register rs, int32_t imm19) {
@@ -2175,6 +2148,21 @@
GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
}
+// Byte swap.
+void Assembler::wsbh(Register rd, Register rt) {
+ DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+ GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
+}
+
+void Assembler::seh(Register rd, Register rt) {
+ DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+ GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
+}
+
+void Assembler::seb(Register rd, Register rt) {
+ DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+ GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
+}
// --------Coprocessor-instructions----------------
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index c595cc9..8f4f9d9 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -125,8 +125,6 @@
Register r = {code};
return r;
}
- const char* ToString();
- bool IsAllocatable() const;
bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
bool is(Register reg) const { return reg_code == reg.reg_code; }
int code() const {
@@ -155,6 +153,8 @@
Register ToRegister(int num);
+static const bool kSimpleFPAliasing = true;
+
// Coprocessor register.
struct FPURegister {
enum Code {
@@ -173,8 +173,6 @@
// to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
// number of Double regs (64-bit regs, or FPU-reg-pairs).
- const char* ToString();
- bool IsAllocatable() const;
bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
bool is(FPURegister reg) const { return reg_code == reg.reg_code; }
FPURegister low() const {
@@ -850,6 +848,10 @@
void bitswap(Register rd, Register rt);
void align(Register rd, Register rs, Register rt, uint8_t bp);
+ void wsbh(Register rd, Register rt);
+ void seh(Register rd, Register rt);
+ void seb(Register rd, Register rt);
+
// --------Coprocessor-instructions----------------
// Load, store, and move.
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 76d0640..7d9d080 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -17,10 +17,7 @@
#define __ ACCESS_MASM(masm)
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
- CFunctionId id,
- BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// ----------- S t a t e -------------
// -- a0 : number of arguments excluding receiver
// -- a1 : target
@@ -39,23 +36,8 @@
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// Insert extra arguments.
- int num_extra_args = 0;
- switch (extra_args) {
- case BuiltinExtraArguments::kTarget:
- __ Push(a1);
- ++num_extra_args;
- break;
- case BuiltinExtraArguments::kNewTarget:
- __ Push(a3);
- ++num_extra_args;
- break;
- case BuiltinExtraArguments::kTargetAndNewTarget:
- __ Push(a1, a3);
- num_extra_args += 2;
- break;
- case BuiltinExtraArguments::kNone:
- break;
- }
+ const int num_extra_args = 2;
+ __ Push(a1, a3);
// JumpToExternalReference expects a0 to contain the number of arguments
// including the receiver and the extra arguments.
@@ -145,6 +127,8 @@
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
+ // -- a1 : function
+ // -- cp : context
// -- ra : return address
// -- sp[(argc - n) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver
@@ -154,9 +138,9 @@
: Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or
- // +Infinity), with the tagged value in a1 and the double value in f0.
- __ LoadRoot(a1, root_index);
- __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+ // +Infinity), with the tagged value in t2 and the double value in f0.
+ __ LoadRoot(t2, root_index);
+ __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ Addu(a3, a0, Operand(1));
Label done_loop, loop;
@@ -171,35 +155,39 @@
__ lw(a2, MemOperand(at));
// Load the double value of the parameter into f2, maybe converting the
- // parameter to a number first using the ToNumberStub if necessary.
+ // parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(a2, &convert_smi);
__ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset));
__ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number);
{
- // Parameter is not a Number, use the ToNumberStub to convert it.
- FrameScope scope(masm, StackFrame::INTERNAL);
+ // Parameter is not a Number, use the ToNumber builtin to convert it.
+ FrameScope scope(masm, StackFrame::MANUAL);
+ __ Push(ra, fp);
+ __ Move(fp, sp);
+ __ Push(cp, a1);
__ SmiTag(a0);
__ SmiTag(a3);
- __ Push(a0, a1, a3);
+ __ Push(a0, t2, a3);
__ mov(a0, a2);
- ToNumberStub stub(masm->isolate());
- __ CallStub(&stub);
+ __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(a2, v0);
- __ Pop(a0, a1, a3);
+ __ Pop(a0, t2, a3);
{
// Restore the double accumulator value (f0).
Label restore_smi, done_restore;
- __ JumpIfSmi(a1, &restore_smi);
- __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+ __ JumpIfSmi(t2, &restore_smi);
+ __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&done_restore);
__ bind(&restore_smi);
- __ SmiToDoubleFPURegister(a1, f0, t0);
+ __ SmiToDoubleFPURegister(t2, f0, t0);
__ bind(&done_restore);
}
__ SmiUntag(a3);
__ SmiUntag(a0);
+ __ Pop(cp, a1);
+ __ Pop(ra, fp);
}
__ jmp(&convert);
__ bind(&convert_number);
@@ -227,20 +215,20 @@
__ Branch(&set_value, ne, t1, Operand(t8));
__ jmp(&loop);
__ bind(&set_value);
- __ mov(a1, a2);
+ __ mov(t2, a2);
__ jmp(&loop);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
- __ LoadRoot(a1, Heap::kNanValueRootIndex);
- __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+ __ LoadRoot(t2, Heap::kNanValueRootIndex);
+ __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&loop);
}
__ bind(&done_loop);
__ Lsa(sp, sp, a3, kPointerSizeLog2);
__ Ret(USE_DELAY_SLOT);
- __ mov(v0, a1); // In delay slot.
+ __ mov(v0, t2); // In delay slot.
}
// static
@@ -265,8 +253,7 @@
}
// 2a. Convert first argument to number.
- ToNumberStub stub(masm->isolate());
- __ TailCallStub(&stub);
+ __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
// 2b. No arguments, return +0.
__ bind(&no_arguments);
@@ -314,8 +301,7 @@
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1, a3);
- ToNumberStub stub(masm->isolate());
- __ CallStub(&stub);
+ __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ Move(a0, v0);
__ Pop(a1, a3);
}
@@ -829,8 +815,8 @@
__ AssertGeneratorObject(a1);
// Store input value into generator object.
- __ sw(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOffset));
- __ RecordWriteField(a1, JSGeneratorObject::kInputOffset, v0, a3,
+ __ sw(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
+ __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
kRAHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object.
@@ -841,20 +827,22 @@
__ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
// Flood function if we are stepping.
- Label skip_flooding;
- ExternalReference step_in_enabled =
- ExternalReference::debug_step_in_enabled_address(masm->isolate());
- __ li(t1, Operand(step_in_enabled));
+ Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+ Label stepping_prepared;
+ ExternalReference last_step_action =
+ ExternalReference::debug_last_step_action_address(masm->isolate());
+ STATIC_ASSERT(StepFrame > StepIn);
+ __ li(t1, Operand(last_step_action));
__ lb(t1, MemOperand(t1));
- __ Branch(&skip_flooding, eq, t1, Operand(zero_reg));
- {
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ Push(a1, a2, t0);
- __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
- __ Pop(a1, a2);
- __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
- }
- __ bind(&skip_flooding);
+ __ Branch(&prepare_step_in_if_stepping, ge, t1, Operand(StepIn));
+
+ // Flood function if we need to continue stepping in the suspended generator.
+ ExternalReference debug_suspended_generator =
+ ExternalReference::debug_suspended_generator_address(masm->isolate());
+ __ li(t1, Operand(debug_suspended_generator));
+ __ lw(t1, MemOperand(t1));
+ __ Branch(&prepare_step_in_suspended_generator, eq, a1, Operand(t1));
+ __ bind(&stepping_prepared);
// Push receiver.
__ lw(t1, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
@@ -950,6 +938,42 @@
__ Move(v0, a1); // Continuation expects generator object in v0.
__ Jump(a3);
}
+
+ __ bind(&prepare_step_in_if_stepping);
+ {
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1, a2, t0);
+ __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+ __ Pop(a1, a2);
+ }
+ __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+ __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+
+ __ bind(&prepare_step_in_suspended_generator);
+ {
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1, a2);
+ __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+ __ Pop(a1, a2);
+ }
+ __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+ __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+}
+
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+ Register args_count = scratch;
+
+ // Get the arguments + receiver count.
+ __ lw(args_count,
+ MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+ __ lw(args_count,
+ FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+ // Leave the frame (also dropping the register file).
+ __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+ // Drop receiver + arguments.
+ __ Addu(sp, sp, args_count);
}
// Generate code for entering a JS function with the interpreter.
@@ -1054,16 +1078,7 @@
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in v0.
-
- // Get the arguments + reciever count.
- __ lw(t0, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
- __ lw(t0, FieldMemOperand(t0, BytecodeArray::kParameterSizeOffset));
-
- // Leave the frame (also dropping the register file).
- __ LeaveFrame(StackFrame::JAVA_SCRIPT);
-
- // Drop receiver + arguments and return.
- __ Addu(sp, sp, t0);
+ LeaveInterpreterFrame(masm, t0);
__ Jump(ra);
// Load debug copy of the bytecode array.
@@ -1085,6 +1100,31 @@
__ Jump(t0);
}
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+ // Save the function and context for call to CompileBaseline.
+ __ lw(a1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+ __ lw(kContextRegister,
+ MemOperand(fp, StandardFrameConstants::kContextOffset));
+
+ // Leave the frame before recompiling for baseline so that we don't count as
+ // an activation on the stack.
+ LeaveInterpreterFrame(masm, t0);
+
+ {
+ FrameScope frame_scope(masm, StackFrame::INTERNAL);
+ // Push return value.
+ __ push(v0);
+
+ // Push function as argument and compile for baseline.
+ __ push(a1);
+ __ CallRuntime(Runtime::kCompileBaseline);
+
+ // Restore return value.
+ __ pop(v0);
+ }
+ __ Jump(ra);
+}
+
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -1241,13 +1281,28 @@
SharedFunctionInfo::kOffsetToPreviousOsrAstId));
const int bailout_id = BailoutId::None().ToInt();
__ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
+
// Literals available?
+ Label got_literals, maybe_cleared_weakcell;
__ lw(temp, FieldMemOperand(array_pointer,
SharedFunctionInfo::kOffsetToPreviousLiterals));
+ // temp contains either a WeakCell pointing to the literals array or the
+ // literals array directly.
+ STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+ __ lw(t0, FieldMemOperand(temp, WeakCell::kValueOffset));
+ __ JumpIfSmi(t0, &maybe_cleared_weakcell);
+ // t0 is a pointer, therefore temp is a WeakCell pointing to a literals array.
__ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
- __ JumpIfSmi(temp, &gotta_call_runtime);
+ __ jmp(&got_literals);
+
+ // t0 is a smi. If it's 0, then we are looking at a cleared WeakCell
+ // around the literals array, and we should visit the runtime. If it's > 0,
+ // then temp already contains the literals array.
+ __ bind(&maybe_cleared_weakcell);
+ __ Branch(&gotta_call_runtime, eq, t0, Operand(Smi::FromInt(0)));
// Save the literals in the closure.
+ __ bind(&got_literals);
__ lw(t0, MemOperand(sp, 0));
__ sw(temp, FieldMemOperand(t0, JSFunction::kLiteralsOffset));
__ push(index);
@@ -1660,6 +1715,9 @@
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
// ----------- S t a t e -------------
+ // -- a0 : number of arguments
+ // -- a1 : function
+ // -- cp : context
// -- sp[0] : receiver
// -----------------------------------
@@ -1699,7 +1757,14 @@
// 3. Raise a TypeError if the receiver is not a date.
__ bind(&receiver_not_date);
- __ TailCallRuntime(Runtime::kThrowNotDateError);
+ {
+ FrameScope scope(masm, StackFrame::MANUAL);
+ __ Push(a0, ra, fp);
+ __ Move(fp, sp);
+ __ Push(cp, a1);
+ __ Push(Smi::FromInt(0));
+ __ CallRuntime(Runtime::kThrowNotDateError);
+ }
}
// static
@@ -2697,6 +2762,83 @@
__ TailCallRuntime(Runtime::kAllocateInTargetSpace);
}
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+ // The StringToNumber stub takes on argument in a0.
+ __ AssertString(a0);
+
+ // Check if string has a cached array index.
+ Label runtime;
+ __ lw(a2, FieldMemOperand(a0, String::kHashFieldOffset));
+ __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
+ __ Branch(&runtime, ne, at, Operand(zero_reg));
+ __ IndexFromHash(a2, v0);
+ __ Ret();
+
+ __ bind(&runtime);
+ {
+ FrameScope frame(masm, StackFrame::INTERNAL);
+ // Push argument.
+ __ Push(a0);
+ // We cannot use a tail call here because this builtin can also be called
+ // from wasm.
+ __ CallRuntime(Runtime::kStringToNumber);
+ }
+ __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in a0.
+ Label not_smi;
+ __ JumpIfNotSmi(a0, ¬_smi);
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ __ bind(¬_smi);
+
+ Label not_heap_number;
+ __ GetObjectType(a0, a1, a1);
+ // a0: receiver
+ // a1: receiver instance type
+ __ Branch(¬_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ __ bind(¬_heap_number);
+
+ __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+ RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+ // The NonNumberToNumber stub takes on argument in a0.
+ __ AssertNotNumber(a0);
+
+ Label not_string;
+ __ GetObjectType(a0, a1, a1);
+ // a0: receiver
+ // a1: receiver instance type
+ __ Branch(¬_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
+ __ Jump(masm->isolate()->builtins()->StringToNumber(),
+ RelocInfo::CODE_TARGET);
+ __ bind(¬_string);
+
+ Label not_oddball;
+ __ Branch(¬_oddball, ne, a1, Operand(ODDBALL_TYPE));
+ __ Ret(USE_DELAY_SLOT);
+ __ lw(v0, FieldMemOperand(a0, Oddball::kToNumberOffset)); // In delay slot.
+ __ bind(¬_oddball);
+ {
+ FrameScope frame(masm, StackFrame::INTERNAL);
+ // Push argument.
+ __ Push(a0);
+ // We cannot use a tail call here because this builtin can also be called
+ // from wasm.
+ __ CallRuntime(Runtime::kToNumber);
+ }
+ __ Ret();
+}
+
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// State setup as expected by MacroAssembler::InvokePrologue.
// ----------- S t a t e -------------
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 4084964..3213677 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -21,70 +21,29 @@
namespace v8 {
namespace internal {
+#define __ ACCESS_MASM(masm)
-static void InitializeArrayConstructorDescriptor(
- Isolate* isolate, CodeStubDescriptor* descriptor,
- int constant_stack_parameter_count) {
- Address deopt_handler = Runtime::FunctionForId(
- Runtime::kArrayConstructor)->entry;
-
- if (constant_stack_parameter_count == 0) {
- descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
- JS_FUNCTION_STUB_MODE);
- } else {
- descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
- JS_FUNCTION_STUB_MODE);
- }
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+ __ sll(t9, a0, kPointerSizeLog2);
+ __ Addu(t9, sp, t9);
+ __ sw(a1, MemOperand(t9, 0));
+ __ Push(a1);
+ __ Push(a2);
+ __ Addu(a0, a0, Operand(3));
+ __ TailCallRuntime(Runtime::kNewArray);
}
-
-static void InitializeInternalArrayConstructorDescriptor(
- Isolate* isolate, CodeStubDescriptor* descriptor,
- int constant_stack_parameter_count) {
- Address deopt_handler = Runtime::FunctionForId(
- Runtime::kInternalArrayConstructor)->entry;
-
- if (constant_stack_parameter_count == 0) {
- descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
- JS_FUNCTION_STUB_MODE);
- } else {
- descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
- JS_FUNCTION_STUB_MODE);
- }
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Address deopt_handler = Runtime::FunctionForId(Runtime::kArrayPush)->entry;
descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
}
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
CodeStubDescriptor* descriptor) {
- InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+ Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+ descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
}
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
Condition cc);
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
@@ -1021,7 +980,7 @@
CEntryStub::GenerateAheadOfTime(isolate);
StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
- ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+ CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
CreateWeakCellStub::GenerateAheadOfTime(isolate);
BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1440,7 +1399,6 @@
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
- STRING_INDEX_IS_ARRAY_INDEX,
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
@@ -1920,6 +1878,7 @@
// a2 : feedback vector
// a3 : slot in feedback vector (Smi)
Label initialize, done, miss, megamorphic, not_array_function;
+ Label done_initialize_count, done_increment_count;
DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
masm->isolate()->heap()->megamorphic_symbol());
@@ -1938,7 +1897,7 @@
Register feedback_map = t1;
Register weak_value = t4;
__ lw(weak_value, FieldMemOperand(t2, WeakCell::kValueOffset));
- __ Branch(&done, eq, a1, Operand(weak_value));
+ __ Branch(&done_increment_count, eq, a1, Operand(weak_value));
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&done, eq, t2, Operand(at));
__ lw(feedback_map, FieldMemOperand(t2, HeapObject::kMapOffset));
@@ -1960,7 +1919,7 @@
// Make sure the function is the Array() function
__ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, t2);
__ Branch(&megamorphic, ne, a1, Operand(t2));
- __ jmp(&done);
+ __ jmp(&done_increment_count);
__ bind(&miss);
@@ -1987,11 +1946,27 @@
// slot.
CreateAllocationSiteStub create_stub(masm->isolate());
CallStubInRecordCallTarget(masm, &create_stub);
- __ Branch(&done);
+ __ Branch(&done_initialize_count);
__ bind(¬_array_function);
CreateWeakCellStub weak_cell_stub(masm->isolate());
CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+ __ bind(&done_initialize_count);
+ // Initialize the call counter.
+ __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
+ __ li(t0, Operand(Smi::FromInt(1)));
+ __ Branch(USE_DELAY_SLOT, &done);
+ __ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+
+ __ bind(&done_increment_count);
+
+ // Increment the call count for monomorphic function calls.
+ __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
+ __ lw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+ __ Addu(t0, t0, Operand(Smi::FromInt(1)));
+ __ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+
__ bind(&done);
}
@@ -2052,7 +2027,7 @@
// Increment the call count for monomorphic function calls.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
__ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
- __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+ __ Addu(a3, a3, Operand(Smi::FromInt(1)));
__ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ mov(a2, t0);
@@ -2098,7 +2073,7 @@
// Increment the call count for monomorphic function calls.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
__ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
- __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+ __ Addu(a3, a3, Operand(Smi::FromInt(1)));
__ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ bind(&call_function);
@@ -2169,7 +2144,7 @@
// Initialize the call counter.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
- __ li(t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+ __ li(t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
// Store the function. Use a stub since we need a frame for allocation.
@@ -2269,13 +2244,7 @@
} else {
__ Push(object_, index_);
}
- if (index_flags_ == STRING_INDEX_IS_NUMBER) {
- __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
- } else {
- DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
- // NumberToSmi discards numbers that are not exact integers.
- __ CallRuntime(Runtime::kNumberToSmi);
- }
+ __ CallRuntime(Runtime::kNumberToSmi);
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
@@ -2617,74 +2586,13 @@
// a3: from index (untagged)
__ SmiTag(a3, a3);
StringCharAtGenerator generator(v0, a3, a2, v0, &runtime, &runtime, &runtime,
- STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+ RECEIVER_IS_STRING);
generator.GenerateFast(masm);
__ DropAndRet(3);
generator.SkipSlow(masm, &runtime);
}
-void ToNumberStub::Generate(MacroAssembler* masm) {
- // The ToNumber stub takes one argument in a0.
- Label not_smi;
- __ JumpIfNotSmi(a0, ¬_smi);
- __ Ret(USE_DELAY_SLOT);
- __ mov(v0, a0);
- __ bind(¬_smi);
-
- Label not_heap_number;
- __ GetObjectType(a0, a1, a1);
- // a0: receiver
- // a1: receiver instance type
- __ Branch(¬_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
- __ Ret(USE_DELAY_SLOT);
- __ mov(v0, a0);
- __ bind(¬_heap_number);
-
- NonNumberToNumberStub stub(masm->isolate());
- __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
- // The NonNumberToNumber stub takes on argument in a0.
- __ AssertNotNumber(a0);
-
- Label not_string;
- __ GetObjectType(a0, a1, a1);
- // a0: receiver
- // a1: receiver instance type
- __ Branch(¬_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
- StringToNumberStub stub(masm->isolate());
- __ TailCallStub(&stub);
- __ bind(¬_string);
-
- Label not_oddball;
- __ Branch(¬_oddball, ne, a1, Operand(ODDBALL_TYPE));
- __ Ret(USE_DELAY_SLOT);
- __ lw(v0, FieldMemOperand(a0, Oddball::kToNumberOffset)); // In delay slot.
- __ bind(¬_oddball);
-
- __ Push(a0); // Push argument.
- __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
- // The StringToNumber stub takes on argument in a0.
- __ AssertString(a0);
-
- // Check if string has a cached array index.
- Label runtime;
- __ lw(a2, FieldMemOperand(a0, String::kHashFieldOffset));
- __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
- __ Branch(&runtime, ne, at, Operand(zero_reg));
- __ IndexFromHash(a2, v0);
- __ Ret();
-
- __ bind(&runtime);
- __ Push(a0); // Push argument.
- __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
void ToStringStub::Generate(MacroAssembler* masm) {
// The ToString stub takes on argument in a0.
Label is_number;
@@ -2865,7 +2773,7 @@
// Load a2 with the allocation site. We stick an undefined dummy value here
// and replace it with the real allocation site later when we instantiate this
// stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
- __ li(a2, handle(isolate()->heap()->undefined_value()));
+ __ li(a2, isolate()->factory()->undefined_value());
// Make sure that we actually patched the allocation site.
if (FLAG_debug_code) {
@@ -3760,14 +3668,14 @@
void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
__ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
- LoadICStub stub(isolate(), state());
+ LoadICStub stub(isolate());
stub.GenerateForTrampoline(masm);
}
void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
__ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
- KeyedLoadICStub stub(isolate(), state());
+ KeyedLoadICStub stub(isolate());
stub.GenerateForTrampoline(masm);
}
@@ -4384,19 +4292,13 @@
}
}
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
isolate);
ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
isolate);
- ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
- isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
- Isolate* isolate) {
+ ArrayNArgumentsConstructorStub stub(isolate);
+ stub.GetCode();
ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
for (int i = 0; i < 2; i++) {
// For internal arrays we only need a few things.
@@ -4404,8 +4306,6 @@
stubh1.GetCode();
InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
stubh2.GetCode();
- InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
- stubh3.GetCode();
}
}
@@ -4424,13 +4324,15 @@
CreateArrayDispatchOneArgument(masm, mode);
__ bind(¬_one_case);
- CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+ ArrayNArgumentsConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
} else if (argument_count() == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
} else if (argument_count() == ONE) {
CreateArrayDispatchOneArgument(masm, mode);
} else if (argument_count() == MORE_THAN_ONE) {
- CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+ ArrayNArgumentsConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
} else {
UNREACHABLE();
}
@@ -4514,7 +4416,7 @@
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0, lo, a0, Operand(1));
- InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+ ArrayNArgumentsConstructorStub stubN(isolate());
__ TailCallStub(&stubN, hi, a0, Operand(1));
if (IsFastPackedElementsKind(kind)) {
@@ -4738,10 +4640,10 @@
// specified by the function's internal formal parameter count.
Label rest_parameters;
__ lw(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
- __ lw(a1,
- FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
- __ Subu(a0, a0, Operand(a1));
+ __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+ __ lw(a3,
+ FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
+ __ Subu(a0, a0, Operand(a3));
__ Branch(&rest_parameters, gt, a0, Operand(zero_reg));
// Return an empty rest parameter array.
@@ -4788,15 +4690,16 @@
// ----------- S t a t e -------------
// -- cp : context
// -- a0 : number of rest parameters (tagged)
+ // -- a1 : function
// -- a2 : pointer to first rest parameters
// -- ra : return address
// -----------------------------------
// Allocate space for the rest parameter array plus the backing store.
Label allocate, done_allocate;
- __ li(a1, Operand(JSArray::kSize + FixedArray::kHeaderSize));
- __ Lsa(a1, a1, a0, kPointerSizeLog2 - 1);
- __ Allocate(a1, v0, a3, t0, &allocate, NO_ALLOCATION_FLAGS);
+ __ li(t0, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+ __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1);
+ __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Setup the elements array in v0.
@@ -4829,16 +4732,24 @@
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a3); // In delay slot
- // Fall back to %AllocateInNewSpace.
+ // Fall back to %AllocateInNewSpace (if not too big).
+ Label too_big_for_new_space;
__ bind(&allocate);
+ __ Branch(&too_big_for_new_space, gt, t0,
+ Operand(Page::kMaxRegularHeapObjectSize));
{
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(a1);
- __ Push(a0, a2, a1);
+ __ SmiTag(t0);
+ __ Push(a0, a2, t0);
__ CallRuntime(Runtime::kAllocateInNewSpace);
__ Pop(a0, a2);
}
__ jmp(&done_allocate);
+
+ // Fall back to %NewStrictArguments.
+ __ bind(&too_big_for_new_space);
+ __ Push(a1);
+ __ TailCallRuntime(Runtime::kNewStrictArguments);
}
}
@@ -5104,9 +5015,9 @@
__ Branch(&arguments_adaptor, eq, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
{
- __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+ __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a0,
- FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
+ FieldMemOperand(t0, SharedFunctionInfo::kFormalParameterCountOffset));
__ Lsa(a2, a2, a0, kPointerSizeLog2 - 1);
__ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
1 * kPointerSize));
@@ -5124,15 +5035,16 @@
// ----------- S t a t e -------------
// -- cp : context
// -- a0 : number of rest parameters (tagged)
+ // -- a1 : function
// -- a2 : pointer to first rest parameters
// -- ra : return address
// -----------------------------------
// Allocate space for the strict arguments object plus the backing store.
Label allocate, done_allocate;
- __ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
- __ Lsa(a1, a1, a0, kPointerSizeLog2 - 1);
- __ Allocate(a1, v0, a3, t0, &allocate, NO_ALLOCATION_FLAGS);
+ __ li(t0, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+ __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1);
+ __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Setup the elements array in v0.
@@ -5165,46 +5077,24 @@
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a3); // In delay slot
- // Fall back to %AllocateInNewSpace.
+ // Fall back to %AllocateInNewSpace (if not too big).
+ Label too_big_for_new_space;
__ bind(&allocate);
+ __ Branch(&too_big_for_new_space, gt, t0,
+ Operand(Page::kMaxRegularHeapObjectSize));
{
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(a1);
- __ Push(a0, a2, a1);
+ __ SmiTag(t0);
+ __ Push(a0, a2, t0);
__ CallRuntime(Runtime::kAllocateInNewSpace);
__ Pop(a0, a2);
}
__ jmp(&done_allocate);
-}
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
- Register context_reg = cp;
- Register slot_reg = a2;
- Register result_reg = v0;
- Label slow_case;
-
- // Go up context chain to the script context.
- for (int i = 0; i < depth(); ++i) {
- __ lw(result_reg, ContextMemOperand(context_reg, Context::PREVIOUS_INDEX));
- context_reg = result_reg;
- }
-
- // Load the PropertyCell value at the specified slot.
- __ Lsa(at, context_reg, slot_reg, kPointerSizeLog2);
- __ lw(result_reg, ContextMemOperand(at, 0));
- __ lw(result_reg, FieldMemOperand(result_reg, PropertyCell::kValueOffset));
-
- // Check that value is not the_hole.
- __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
- __ Branch(&slow_case, eq, result_reg, Operand(at));
- __ Ret();
-
- // Fallback to the runtime.
- __ bind(&slow_case);
- __ SmiTag(slot_reg);
- __ Push(slot_reg);
- __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+ // Fall back to %NewStrictArguments.
+ __ bind(&too_big_for_new_space);
+ __ Push(a1);
+ __ TailCallRuntime(Runtime::kNewStrictArguments);
}
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 63bbda3..07cab80 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -16,60 +16,6 @@
#define __ masm.
-
-#if defined(USE_SIMULATOR)
-byte* fast_exp_mips_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
- return Simulator::current(isolate)->CallFP(fast_exp_mips_machine_code, x, 0);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
- size_t actual_size;
- byte* buffer =
- static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
- if (buffer == nullptr) return nullptr;
- ExternalReference::InitializeMathExpData();
-
- MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
- CodeObjectRequired::kNo);
-
- {
- DoubleRegister input = f12;
- DoubleRegister result = f0;
- DoubleRegister double_scratch1 = f4;
- DoubleRegister double_scratch2 = f6;
- Register temp1 = t0;
- Register temp2 = t1;
- Register temp3 = t2;
-
- __ MovFromFloatParameter(input);
- __ Push(temp3, temp2, temp1);
- MathExpGenerator::EmitMathExp(
- &masm, input, result, double_scratch1, double_scratch2,
- temp1, temp2, temp3);
- __ Pop(temp3, temp2, temp1);
- __ MovToFloatResult(result);
- __ Ret();
- }
-
- CodeDesc desc;
- masm.GetCode(&desc);
- DCHECK(!RelocInfo::RequiresRelocation(desc));
-
- Assembler::FlushICache(isolate, buffer, actual_size);
- base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
- return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
- fast_exp_mips_machine_code = buffer;
- return &fast_exp_simulator;
-#endif
-}
-
-
#if defined(V8_HOST_ARCH_MIPS)
MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
MemCopyUint8Function stub) {
@@ -1092,95 +1038,6 @@
__ bind(&done);
}
-
-static MemOperand ExpConstant(int index, Register base) {
- return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
- DoubleRegister input,
- DoubleRegister result,
- DoubleRegister double_scratch1,
- DoubleRegister double_scratch2,
- Register temp1,
- Register temp2,
- Register temp3) {
- DCHECK(!input.is(result));
- DCHECK(!input.is(double_scratch1));
- DCHECK(!input.is(double_scratch2));
- DCHECK(!result.is(double_scratch1));
- DCHECK(!result.is(double_scratch2));
- DCHECK(!double_scratch1.is(double_scratch2));
- DCHECK(!temp1.is(temp2));
- DCHECK(!temp1.is(temp3));
- DCHECK(!temp2.is(temp3));
- DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
- DCHECK(!masm->serializer_enabled()); // External references not serializable.
-
- Label zero, infinity, done;
-
- __ li(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
- __ ldc1(double_scratch1, ExpConstant(0, temp3));
- __ BranchF(&zero, NULL, ge, double_scratch1, input);
-
- __ ldc1(double_scratch2, ExpConstant(1, temp3));
- __ BranchF(&infinity, NULL, ge, input, double_scratch2);
-
- __ ldc1(double_scratch1, ExpConstant(3, temp3));
- __ ldc1(result, ExpConstant(4, temp3));
- __ mul_d(double_scratch1, double_scratch1, input);
- __ add_d(double_scratch1, double_scratch1, result);
- __ FmoveLow(temp2, double_scratch1);
- __ sub_d(double_scratch1, double_scratch1, result);
- __ ldc1(result, ExpConstant(6, temp3));
- __ ldc1(double_scratch2, ExpConstant(5, temp3));
- __ mul_d(double_scratch1, double_scratch1, double_scratch2);
- __ sub_d(double_scratch1, double_scratch1, input);
- __ sub_d(result, result, double_scratch1);
- __ mul_d(double_scratch2, double_scratch1, double_scratch1);
- __ mul_d(result, result, double_scratch2);
- __ ldc1(double_scratch2, ExpConstant(7, temp3));
- __ mul_d(result, result, double_scratch2);
- __ sub_d(result, result, double_scratch1);
- // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
- DCHECK(*reinterpret_cast<double*>
- (ExternalReference::math_exp_constants(8).address()) == 1);
- __ Move(double_scratch2, 1.);
- __ add_d(result, result, double_scratch2);
- __ srl(temp1, temp2, 11);
- __ Ext(temp2, temp2, 0, 11);
- __ Addu(temp1, temp1, Operand(0x3ff));
-
- // Must not call ExpConstant() after overwriting temp3!
- __ li(temp3, Operand(ExternalReference::math_exp_log_table()));
- __ Lsa(temp3, temp3, temp2, 3);
- __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset));
- __ lw(temp3, MemOperand(temp3, Register::kExponentOffset));
- // The first word is loaded is the lower number register.
- if (temp2.code() < temp3.code()) {
- __ sll(at, temp1, 20);
- __ Or(temp1, temp3, at);
- __ Move(double_scratch1, temp2, temp1);
- } else {
- __ sll(at, temp1, 20);
- __ Or(temp1, temp2, at);
- __ Move(double_scratch1, temp3, temp1);
- }
- __ mul_d(result, result, double_scratch1);
- __ BranchShort(&done);
-
- __ bind(&zero);
- __ Move(result, kDoubleRegZero);
- __ BranchShort(&done);
-
- __ bind(&infinity);
- __ ldc1(result, ExpConstant(2, temp3));
-
- __ bind(&done);
-}
-
#ifdef DEBUG
// nop(CODE_AGE_MARKER_NOP)
static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180;
diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h
index ad7abb3..a4f8184 100644
--- a/src/mips/codegen-mips.h
+++ b/src/mips/codegen-mips.h
@@ -29,23 +29,6 @@
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
};
-
-class MathExpGenerator : public AllStatic {
- public:
- // Register input isn't modified. All other registers are clobbered.
- static void EmitMathExp(MacroAssembler* masm,
- DoubleRegister input,
- DoubleRegister result,
- DoubleRegister double_scratch1,
- DoubleRegister double_scratch2,
- Register temp1,
- Register temp2,
- Register temp3);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
} // namespace internal
} // namespace v8
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h
index f50a849..8301c5e 100644
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -1186,11 +1186,10 @@
int sa = SaFieldRaw() >> kSaShift;
switch (sa) {
case BITSWAP:
- return kRegisterType;
case WSBH:
case SEB:
case SEH:
- return kUnsupported;
+ return kRegisterType;
}
sa >>= kBp2Bits;
switch (sa) {
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
index e9caaad..478b9df 100644
--- a/src/mips/deoptimizer-mips.cc
+++ b/src/mips/deoptimizer-mips.cc
@@ -117,8 +117,7 @@
// Save all FPU registers before messing with them.
__ Subu(sp, sp, Operand(kDoubleRegsSize));
- const RegisterConfiguration* config =
- RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+ const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
int code = config->GetAllocatableDoubleCode(i);
const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc
index e1890ee..bd07874 100644
--- a/src/mips/disasm-mips.cc
+++ b/src/mips/disasm-mips.cc
@@ -1264,11 +1264,30 @@
}
break;
}
- case SEB:
- case SEH:
- case WSBH:
- UNREACHABLE();
+ case SEB: {
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "seb 'rd, 'rt");
+ } else {
+ Unknown(instr);
+ }
break;
+ }
+ case SEH: {
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "seh 'rd, 'rt");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
+ case WSBH: {
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "wsbh 'rd, 'rt");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
default: {
sa >>= kBp2Bits;
switch (sa) {
@@ -1699,7 +1718,7 @@
namespace disasm {
const char* NameConverter::NameOfAddress(byte* addr) const {
- v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+ v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
return tmp_buffer_.start();
}
@@ -1762,8 +1781,8 @@
buffer[0] = '\0';
byte* prev_pc = pc;
pc += d.InstructionDecode(buffer, pc);
- v8::internal::PrintF(f, "%p %08x %s\n",
- prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+ v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc),
+ *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
}
}
diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc
index 30a7a74..a8e6e57 100644
--- a/src/mips/interface-descriptors-mips.cc
+++ b/src/mips/interface-descriptors-mips.cc
@@ -11,6 +11,14 @@
const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+ CallInterfaceDescriptorData* data, int register_parameter_count) {
+ const Register default_stub_registers[] = {a0, a1, a2, a3, t0};
+ CHECK_LE(static_cast<size_t>(register_parameter_count),
+ arraysize(default_stub_registers));
+ data->InitializePlatformSpecific(register_parameter_count,
+ default_stub_registers);
+}
const Register LoadDescriptor::ReceiverRegister() { return a1; }
const Register LoadDescriptor::NameRegister() { return a2; }
@@ -39,9 +47,6 @@
const Register StoreTransitionDescriptor::MapRegister() { return a3; }
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return a2; }
-
-
const Register StoreGlobalViaContextDescriptor::SlotRegister() { return a2; }
const Register StoreGlobalViaContextDescriptor::ValueRegister() { return a0; }
@@ -63,8 +68,6 @@
const Register GrowArrayElementsDescriptor::ObjectRegister() { return a0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return a3; }
-const Register HasPropertyDescriptor::ObjectRegister() { return a0; }
-const Register HasPropertyDescriptor::KeyRegister() { return a3; }
void FastNewClosureDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
@@ -254,43 +257,24 @@
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// register state
// a0 -- number of arguments
// a1 -- function
// a2 -- allocation site with elements kind
- Register registers[] = {a1, a2};
+ Register registers[] = {a1, a2, a0};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
-
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// stack param count needs (constructor pointer, and single argument)
Register registers[] = {a1, a2, a0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
-
-void InternalArrayConstructorConstantArgCountDescriptor::
- InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
- // register state
- // a0 -- number of arguments
- // a1 -- constructor function
- Register registers[] = {a1};
- data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- // stack param count needs (constructor pointer, and single argument)
- Register registers[] = {a1, a0};
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// stack param count needs (arg count)
Register registers[] = {a0};
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 3dbfd6b..86aef38 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -18,6 +18,19 @@
namespace v8 {
namespace internal {
+// Floating point constants.
+const uint32_t kDoubleSignMask = HeapNumber::kSignMask;
+const uint32_t kDoubleExponentShift = HeapNumber::kExponentShift;
+const uint32_t kDoubleNaNShift = kDoubleExponentShift - 1;
+const uint32_t kDoubleNaNMask =
+ HeapNumber::kExponentMask | (1 << kDoubleNaNShift);
+
+const uint32_t kSingleSignMask = kBinary32SignMask;
+const uint32_t kSingleExponentMask = kBinary32ExponentMask;
+const uint32_t kSingleExponentShift = kBinary32ExponentShift;
+const uint32_t kSingleNaNShift = kSingleExponentShift - 1;
+const uint32_t kSingleNaNMask = kSingleExponentMask | (1 << kSingleNaNShift);
+
MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
CodeObjectRequired create_code_object)
: Assembler(arg_isolate, buffer, size),
@@ -30,7 +43,6 @@
}
}
-
void MacroAssembler::Load(Register dst,
const MemOperand& src,
Representation r) {
@@ -67,7 +79,6 @@
}
}
-
void MacroAssembler::LoadRoot(Register destination,
Heap::RootListIndex index) {
lw(destination, MemOperand(s6, index << kPointerSizeLog2));
@@ -1191,6 +1202,79 @@
// ------------Pseudo-instructions-------------
+// Word Swap Byte
+void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
+ DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ if (operand_size == 2) {
+ seh(reg, reg);
+ } else if (operand_size == 1) {
+ seb(reg, reg);
+ }
+ // No need to do any preparation if operand_size is 4
+
+ wsbh(reg, reg);
+ rotr(reg, reg, 16);
+ } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
+ if (operand_size == 1) {
+ sll(reg, reg, 24);
+ sra(reg, reg, 24);
+ } else if (operand_size == 2) {
+ sll(reg, reg, 16);
+ sra(reg, reg, 16);
+ }
+ // No need to do any preparation if operand_size is 4
+
+ Register tmp = t0;
+ Register tmp2 = t1;
+
+ andi(tmp2, reg, 0xFF);
+ sll(tmp2, tmp2, 24);
+ or_(tmp, zero_reg, tmp2);
+
+ andi(tmp2, reg, 0xFF00);
+ sll(tmp2, tmp2, 8);
+ or_(tmp, tmp, tmp2);
+
+ srl(reg, reg, 8);
+ andi(tmp2, reg, 0xFF00);
+ or_(tmp, tmp, tmp2);
+
+ srl(reg, reg, 16);
+ andi(tmp2, reg, 0xFF);
+ or_(tmp, tmp, tmp2);
+
+ or_(reg, tmp, zero_reg);
+ }
+}
+
+void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
+ DCHECK(operand_size == 1 || operand_size == 2);
+
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ if (operand_size == 1) {
+ andi(reg, reg, 0xFF);
+ } else {
+ andi(reg, reg, 0xFFFF);
+ }
+ // No need to do any preparation if operand_size is 4
+
+ wsbh(reg, reg);
+ rotr(reg, reg, 16);
+ } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
+ if (operand_size == 1) {
+ sll(reg, reg, 24);
+ } else {
+ Register tmp = t0;
+
+ andi(tmp, reg, 0xFF00);
+ sll(reg, reg, 24);
+ sll(tmp, tmp, 8);
+ or_(reg, tmp, reg);
+ }
+ }
+}
+
void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
DCHECK(!rd.is(at));
DCHECK(!rs.rm().is(at));
@@ -3832,9 +3916,6 @@
Label start;
bind(&start);
int32_t target_int = reinterpret_cast<int32_t>(target);
- // Must record previous source positions before the
- // li() generates a new code target.
- positions_recorder()->WriteRecordedPositions();
li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
Call(t9, cond, rs, rt, bd);
DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
@@ -4655,9 +4736,7 @@
int elements_offset) {
DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1, scratch2,
scratch3));
- Label smi_value, maybe_nan, have_double_value, is_nan, done;
- Register mantissa_reg = scratch2;
- Register exponent_reg = scratch3;
+ Label smi_value, done;
// Handle smi values specially.
JumpIfSmi(value_reg, &smi_value);
@@ -4669,52 +4748,97 @@
fail,
DONT_DO_SMI_CHECK);
- // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
- // in the exponent.
- li(scratch1, Operand(kHoleNanUpper32 & HeapNumber::kExponentMask));
- lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
- Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1));
+ // Double value, turn potential sNaN into qNan.
+ DoubleRegister double_result = f0;
+ DoubleRegister double_scratch = f2;
- lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
-
- bind(&have_double_value);
- Lsa(scratch1, elements_reg, key_reg, kDoubleSizeLog2 - kSmiTagSize);
- sw(mantissa_reg,
- FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
- + kHoleNanLower32Offset));
- sw(exponent_reg,
- FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
- + kHoleNanUpper32Offset));
- jmp(&done);
-
- bind(&maybe_nan);
- // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
- // it's an Infinity, and the non-NaN code path applies.
- Branch(&is_nan, gt, exponent_reg, Operand(scratch1));
- lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
- Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
- bind(&is_nan);
- // Load canonical NaN for storing into the double array.
- LoadRoot(at, Heap::kNanValueRootIndex);
- lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset));
- lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset));
- jmp(&have_double_value);
+ ldc1(double_result, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
+ Branch(USE_DELAY_SLOT, &done); // Canonicalization is one instruction.
+ FPUCanonicalizeNaN(double_result, double_result);
bind(&smi_value);
+ Register untagged_value = scratch2;
+ SmiUntag(untagged_value, value_reg);
+ mtc1(untagged_value, double_scratch);
+ cvt_d_w(double_result, double_scratch);
+
+ bind(&done);
Addu(scratch1, elements_reg,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
elements_offset));
Lsa(scratch1, scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
// scratch1 is now effective address of the double element
+ sdc1(double_result, MemOperand(scratch1, 0));
+}
- Register untagged_value = scratch2;
- SmiUntag(untagged_value, value_reg);
- mtc1(untagged_value, f2);
- cvt_d_w(f0, f2);
- sdc1(f0, MemOperand(scratch1, 0));
+void MacroAssembler::SubNanPreservePayloadAndSign_s(FloatRegister fd,
+ FloatRegister fs,
+ FloatRegister ft) {
+ FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+ Label check_nan, save_payload, done;
+ Register scratch1 = t8;
+ Register scratch2 = t9;
+
+ sub_s(dest, fs, ft);
+ // Check if the result of subtraction is NaN.
+ BranchF32(nullptr, &check_nan, eq, fs, ft);
+ Branch(USE_DELAY_SLOT, &done);
+ dest.is(fd) ? nop() : mov_s(fd, dest);
+
+ bind(&check_nan);
+ // Check if first operand is a NaN.
+ mfc1(scratch1, fs);
+ BranchF32(nullptr, &save_payload, eq, fs, fs);
+ // Second operand must be a NaN.
+ mfc1(scratch1, ft);
+
+ bind(&save_payload);
+ // Reserve payload.
+ And(scratch1, scratch1,
+ Operand(kSingleSignMask | ((1 << kSingleNaNShift) - 1)));
+ mfc1(scratch2, dest);
+ And(scratch2, scratch2, Operand(kSingleNaNMask));
+ Or(scratch2, scratch2, scratch1);
+ mtc1(scratch2, fd);
+
bind(&done);
}
+void MacroAssembler::SubNanPreservePayloadAndSign_d(DoubleRegister fd,
+ DoubleRegister fs,
+ DoubleRegister ft) {
+ FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+ Label check_nan, save_payload, done;
+ Register scratch1 = t8;
+ Register scratch2 = t9;
+
+ sub_d(dest, fs, ft);
+ // Check if the result of subtraction is NaN.
+ BranchF64(nullptr, &check_nan, eq, fs, ft);
+ Branch(USE_DELAY_SLOT, &done);
+ dest.is(fd) ? nop() : mov_d(fd, dest);
+
+ bind(&check_nan);
+ // Check if first operand is a NaN.
+ Mfhc1(scratch1, fs);
+ mov_s(dest, fs);
+ BranchF64(nullptr, &save_payload, eq, fs, fs);
+ // Second operand must be a NaN.
+ Mfhc1(scratch1, ft);
+ mov_s(dest, ft);
+
+ bind(&save_payload);
+ // Reserve payload.
+ And(scratch1, scratch1,
+ Operand(kDoubleSignMask | ((1 << kDoubleNaNShift) - 1)));
+ Mfhc1(scratch2, dest);
+ And(scratch2, scratch2, Operand(kDoubleNaNMask));
+ Or(scratch2, scratch2, scratch1);
+ Move_s(fd, dest);
+ Mthc1(scratch2, fd);
+
+ bind(&done);
+}
void MacroAssembler::CompareMapAndBranch(Register obj,
Register scratch,
@@ -4778,6 +4902,10 @@
Branch(fail, ne, scratch, Operand(at));
}
+void MacroAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
+ const DoubleRegister src) {
+ sub_d(dst, src, kDoubleRegZero);
+}
void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
li(value, Operand(cell));
@@ -4998,11 +5126,12 @@
const ParameterCount& expected,
const ParameterCount& actual) {
Label skip_flooding;
- ExternalReference step_in_enabled =
- ExternalReference::debug_step_in_enabled_address(isolate());
- li(t0, Operand(step_in_enabled));
+ ExternalReference last_step_action =
+ ExternalReference::debug_last_step_action_address(isolate());
+ STATIC_ASSERT(StepFrame > StepIn);
+ li(t0, Operand(last_step_action));
lb(t0, MemOperand(t0));
- Branch(&skip_flooding, eq, t0, Operand(zero_reg));
+ Branch(&skip_flooding, lt, t0, Operand(StepIn));
{
FrameScope frame(this,
has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -5746,9 +5875,8 @@
void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- lw(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
- lw(vector,
- FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+ lw(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+ lw(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
}
@@ -6662,8 +6790,7 @@
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
- const RegisterConfiguration* config =
- RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+ const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
int code = config->GetAllocatableGeneralCode(i);
Register candidate = Register::from_code(code);
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 2417025..8c6e5bd 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -687,6 +687,10 @@
// ---------------------------------------------------------------------------
// Pseudo-instructions.
+ // Change endianness
+ void ByteSwapSigned(Register reg, int operand_size);
+ void ByteSwapUnsigned(Register reg, int operand_size);
+
void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
void Ulh(Register rd, const MemOperand& rs);
@@ -871,6 +875,12 @@
void Floor_w_d(FPURegister fd, FPURegister fs);
void Ceil_w_d(FPURegister fd, FPURegister fs);
+ // Preserve value of a NaN operand
+ void SubNanPreservePayloadAndSign_s(FPURegister fd, FPURegister fs,
+ FPURegister ft);
+ void SubNanPreservePayloadAndSign_d(FPURegister fd, FPURegister fs,
+ FPURegister ft);
+
// FP32 mode: Move the general purpose register into
// the high part of the double-register pair.
// FP64 mode: Move the general-purpose register into
@@ -1231,6 +1241,9 @@
Handle<WeakCell> cell, Handle<Code> success,
SmiCheckType smi_check_type);
+ // If the value is a NaN, canonicalize the value else, do nothing.
+ void FPUCanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
+
// Get value of the weak cell.
void GetWeakValue(Register value, Handle<WeakCell> cell);
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index f8dc515..71dcda2 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -864,9 +864,7 @@
last_debugger_input_ = input;
}
-
-void Simulator::FlushICache(v8::internal::HashMap* i_cache,
- void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
size_t size) {
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
@@ -887,10 +885,8 @@
}
}
-
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
- v8::internal::HashMap::Entry* entry =
- i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+ base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
if (entry->value == NULL) {
CachePage* new_page = new CachePage();
entry->value = new_page;
@@ -900,9 +896,7 @@
// Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
- intptr_t start,
- int size) {
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
DCHECK(size <= CachePage::kPageSize);
DCHECK(AllOnOnePage(start, size - 1));
DCHECK((start & CachePage::kLineMask) == 0);
@@ -914,9 +908,7 @@
memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
}
-
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
- Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
intptr_t address = reinterpret_cast<intptr_t>(instr);
void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -949,7 +941,7 @@
Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
i_cache_ = isolate_->simulator_i_cache();
if (i_cache_ == NULL) {
- i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+ i_cache_ = new base::HashMap(&ICacheMatch);
isolate_->set_simulator_i_cache(i_cache_);
}
Initialize(isolate);
@@ -1062,10 +1054,10 @@
// static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
Redirection::DeleteChain(first);
if (i_cache != nullptr) {
- for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+ for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
entry = i_cache->Next(entry)) {
delete static_cast<CachePage*>(entry->value);
}
@@ -2088,15 +2080,17 @@
case ExternalReference::BUILTIN_FP_FP_CALL:
case ExternalReference::BUILTIN_COMPARE_CALL:
PrintF("Call to host function at %p with args %f, %f",
- FUNCTION_ADDR(generic_target), dval0, dval1);
+ static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+ dval1);
break;
case ExternalReference::BUILTIN_FP_CALL:
PrintF("Call to host function at %p with arg %f",
- FUNCTION_ADDR(generic_target), dval0);
+ static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
break;
case ExternalReference::BUILTIN_FP_INT_CALL:
PrintF("Call to host function at %p with args %f, %d",
- FUNCTION_ADDR(generic_target), dval0, ival);
+ static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+ ival);
break;
default:
UNREACHABLE();
@@ -2195,13 +2189,15 @@
PrintF(
"Call to host triple returning runtime function %p "
"args %08x, %08x, %08x, %08x, %08x\n",
- FUNCTION_ADDR(target), arg1, arg2, arg3, arg4, arg5);
+ static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
+ arg5);
}
// arg0 is a hidden argument pointing to the return location, so don't
// pass it to the target function.
ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
if (::v8::internal::FLAG_trace_sim) {
- PrintF("Returned { %p, %p, %p }\n", result.x, result.y, result.z);
+ PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
+ static_cast<void*>(result.y), static_cast<void*>(result.z));
}
// Return is passed back in address pointed to by hidden first argument.
ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
@@ -2216,13 +2212,8 @@
PrintF(
"Call to host function at %p "
"args %08x, %08x, %08x, %08x, %08x, %08x\n",
- FUNCTION_ADDR(target),
- arg0,
- arg1,
- arg2,
- arg3,
- arg4,
- arg5);
+ static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
+ arg4, arg5);
}
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
set_register(v0, static_cast<int32_t>(result));
@@ -3842,12 +3833,51 @@
alu_out = static_cast<int32_t>(output);
break;
}
- case SEB:
- case SEH:
- case WSBH:
- alu_out = 0x12345678;
- UNREACHABLE();
+ case SEB: {
+ uint8_t input = static_cast<uint8_t>(rt());
+ uint32_t output = input;
+ uint32_t mask = 0x00000080;
+
+ // Extending sign
+ if (mask & input) {
+ output |= 0xFFFFFF00;
+ }
+
+ alu_out = static_cast<int32_t>(output);
break;
+ }
+ case SEH: {
+ uint16_t input = static_cast<uint16_t>(rt());
+ uint32_t output = input;
+ uint32_t mask = 0x00008000;
+
+ // Extending sign
+ if (mask & input) {
+ output |= 0xFFFF0000;
+ }
+
+ alu_out = static_cast<int32_t>(output);
+ break;
+ }
+ case WSBH: {
+ uint32_t input = static_cast<uint32_t>(rt());
+ uint32_t output = 0;
+
+ uint32_t mask = 0xFF000000;
+ for (int i = 0; i < 4; i++) {
+ uint32_t tmp = mask & input;
+ if (i % 2 == 0) {
+ tmp = tmp >> 8;
+ } else {
+ tmp = tmp << 8;
+ }
+ output = output | tmp;
+ mask = mask >> 8;
+ }
+
+ alu_out = static_cast<int32_t>(output);
+ break;
+ }
default: {
const uint8_t bp = get_instr()->Bp2Value();
sa >>= kBp2Bits;
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index e1c42fd..5c77756 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -75,7 +75,7 @@
// Running with a simulator.
#include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
namespace v8 {
namespace internal {
@@ -216,7 +216,7 @@
// Call on program start.
static void Initialize(Isolate* isolate);
- static void TearDown(HashMap* i_cache, Redirection* first);
+ static void TearDown(base::HashMap* i_cache, Redirection* first);
// V8 generally calls into generated JS code with 5 parameters and into
// generated RegExp code with 7 parameters. This is a convenience function,
@@ -236,8 +236,7 @@
char* last_debugger_input() { return last_debugger_input_; }
// ICache checking.
- static void FlushICache(v8::internal::HashMap* i_cache, void* start,
- size_t size);
+ static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
// Returns true if pc register contains one of the 'special_values' defined
// below (bad_ra, end_sim_pc).
@@ -401,10 +400,9 @@
}
// ICache.
- static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
- static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
- int size);
- static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+ static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+ static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
+ static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
enum Exception {
none,
@@ -450,7 +448,7 @@
char* last_debugger_input_;
// Icache simulation.
- v8::internal::HashMap* i_cache_;
+ base::HashMap* i_cache_;
v8::internal::Isolate* isolate_;