Index: src/x64/macro-assembler-x64.h |
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h |
index b1f886a140517c2c71457828aac0c8030743d455..719c8d3d99e0c7f7a250ad904e3f3c1624dcad89 100644 |
--- a/src/x64/macro-assembler-x64.h |
+++ b/src/x64/macro-assembler-x64.h |
@@ -145,11 +145,11 @@ class MacroAssembler: public Assembler { |
// Check if object is in new space. The condition cc can be equal or |
// not_equal. If it is equal a jump will be done if the object is on new |
// space. The register scratch can be object itself, but it will be clobbered. |
- template <typename LabelType> |
void InNewSpace(Register object, |
Register scratch, |
Condition cc, |
- LabelType* branch); |
+ Label* branch, |
+ Label::Distance near_jump = Label::kFar); |
// For page containing |object| mark region covering [object+offset] |
// dirty. |object| is the object being stored into, |value| is the |
@@ -326,11 +326,11 @@ class MacroAssembler: public Assembler { |
// If either argument is not a smi, jump to on_not_smis and retain |
// the original values of source registers. The destination register |
// may be changed if it's not one of the source registers. |
- template <typename LabelType> |
void SmiOrIfSmis(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smis); |
+ Label* on_not_smis, |
+ Label::Distance near_jump = Label::kFar); |
// Simple comparison of smis. Both sides must be known smis to use these, |
@@ -388,42 +388,45 @@ class MacroAssembler: public Assembler { |
// above with a conditional jump. |
// Jump if the value cannot be represented by a smi. |
- template <typename LabelType> |
- void JumpIfNotValidSmiValue(Register src, LabelType* on_invalid); |
+ void JumpIfNotValidSmiValue(Register src, Label* on_invalid, |
+ Label::Distance near_jump = Label::kFar); |
// Jump if the unsigned integer value cannot be represented by a smi. |
- template <typename LabelType> |
- void JumpIfUIntNotValidSmiValue(Register src, LabelType* on_invalid); |
+ void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid, |
+ Label::Distance near_jump = Label::kFar); |
// Jump to label if the value is a tagged smi. |
- template <typename LabelType> |
- void JumpIfSmi(Register src, LabelType* on_smi); |
+ void JumpIfSmi(Register src, |
+ Label* on_smi, |
+ Label::Distance near_jump = Label::kFar); |
// Jump to label if the value is not a tagged smi. |
- template <typename LabelType> |
- void JumpIfNotSmi(Register src, LabelType* on_not_smi); |
+ void JumpIfNotSmi(Register src, |
+ Label* on_not_smi, |
+ Label::Distance near_jump = Label::kFar); |
// Jump to label if the value is not a non-negative tagged smi. |
- template <typename LabelType> |
- void JumpUnlessNonNegativeSmi(Register src, LabelType* on_not_smi); |
+ void JumpUnlessNonNegativeSmi(Register src, |
+ Label* on_not_smi, |
+ Label::Distance near_jump = Label::kFar); |
// Jump to label if the value, which must be a tagged smi, has value equal |
// to the constant. |
- template <typename LabelType> |
void JumpIfSmiEqualsConstant(Register src, |
Smi* constant, |
- LabelType* on_equals); |
+ Label* on_equals, |
+ Label::Distance near_jump = Label::kFar); |
// Jump if either or both register are not smi values. |
- template <typename LabelType> |
void JumpIfNotBothSmi(Register src1, |
Register src2, |
- LabelType* on_not_both_smi); |
+ Label* on_not_both_smi, |
+ Label::Distance near_jump = Label::kFar); |
// Jump if either or both register are not non-negative smi values. |
- template <typename LabelType> |
void JumpUnlessBothNonNegativeSmi(Register src1, Register src2, |
- LabelType* on_not_both_smi); |
+ Label* on_not_both_smi, |
+ Label::Distance near_jump = Label::kFar); |
// Operations on tagged smi values. |
@@ -433,11 +436,11 @@ class MacroAssembler: public Assembler { |
// Optimistically adds an integer constant to a supposed smi. |
// If the src is not a smi, or the result is not a smi, jump to |
// the label. |
- template <typename LabelType> |
void SmiTryAddConstant(Register dst, |
Register src, |
Smi* constant, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Add an integer constant to a tagged smi, giving a tagged smi as result. |
// No overflow testing on the result is done. |
@@ -449,11 +452,11 @@ class MacroAssembler: public Assembler { |
// Add an integer constant to a tagged smi, giving a tagged smi as result, |
// or jumping to a label if the result cannot be represented by a smi. |
- template <typename LabelType> |
void SmiAddConstant(Register dst, |
Register src, |
Smi* constant, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Subtract an integer constant from a tagged smi, giving a tagged smi as |
// result. No testing on the result is done. Sets the N and Z flags |
@@ -462,32 +465,32 @@ class MacroAssembler: public Assembler { |
// Subtract an integer constant from a tagged smi, giving a tagged smi as |
// result, or jumping to a label if the result cannot be represented by a smi. |
- template <typename LabelType> |
void SmiSubConstant(Register dst, |
Register src, |
Smi* constant, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Negating a smi can give a negative zero or too large positive value. |
// NOTICE: This operation jumps on success, not failure! |
- template <typename LabelType> |
void SmiNeg(Register dst, |
Register src, |
- LabelType* on_smi_result); |
+ Label* on_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Adds smi values and return the result as a smi. |
// If dst is src1, then src1 will be destroyed, even if |
// the operation is unsuccessful. |
- template <typename LabelType> |
void SmiAdd(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
- template <typename LabelType> |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
void SmiAdd(Register dst, |
Register src1, |
const Operand& src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
void SmiAdd(Register dst, |
Register src1, |
@@ -496,21 +499,21 @@ class MacroAssembler: public Assembler { |
// Subtracts smi values and return the result as a smi. |
// If dst is src1, then src1 will be destroyed, even if |
// the operation is unsuccessful. |
- template <typename LabelType> |
void SmiSub(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
void SmiSub(Register dst, |
Register src1, |
Register src2); |
- template <typename LabelType> |
void SmiSub(Register dst, |
Register src1, |
const Operand& src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
void SmiSub(Register dst, |
Register src1, |
@@ -520,27 +523,27 @@ class MacroAssembler: public Assembler { |
// if possible. |
// If dst is src1, then src1 will be destroyed, even if |
// the operation is unsuccessful. |
- template <typename LabelType> |
void SmiMul(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Divides one smi by another and returns the quotient. |
// Clobbers rax and rdx registers. |
- template <typename LabelType> |
void SmiDiv(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Divides one smi by another and returns the remainder. |
// Clobbers rax and rdx registers. |
- template <typename LabelType> |
void SmiMod(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Bitwise operations. |
void SmiNot(Register dst, Register src); |
@@ -554,11 +557,11 @@ class MacroAssembler: public Assembler { |
void SmiShiftLeftConstant(Register dst, |
Register src, |
int shift_value); |
- template <typename LabelType> |
void SmiShiftLogicalRightConstant(Register dst, |
Register src, |
int shift_value, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
void SmiShiftArithmeticRightConstant(Register dst, |
Register src, |
int shift_value); |
@@ -571,11 +574,11 @@ class MacroAssembler: public Assembler { |
// Shifts a smi value to the right, shifting in zero bits at the top, and |
// returns the unsigned intepretation of the result if that is a smi. |
// Uses and clobbers rcx, so dst may not be rcx. |
- template <typename LabelType> |
void SmiShiftLogicalRight(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smi_result); |
+ Label* on_not_smi_result, |
+ Label::Distance near_jump = Label::kFar); |
// Shifts a smi value to the right, sign extending the top, and |
// returns the signed intepretation of the result. That will always |
// be a valid smi value, since it's numerically smaller than the |
@@ -589,11 +592,11 @@ class MacroAssembler: public Assembler { |
// Select the non-smi register of two registers where exactly one is a |
// smi. If neither are smis, jump to the failure label. |
- template <typename LabelType> |
void SelectNonSmi(Register dst, |
Register src1, |
Register src2, |
- LabelType* on_not_smis); |
+ Label* on_not_smis, |
+ Label::Distance near_jump = Label::kFar); |
// Converts, if necessary, a smi to a combination of number and |
// multiplier to be used as a scaled index. |
@@ -629,35 +632,36 @@ class MacroAssembler: public Assembler { |
// String macros. |
// If object is a string, its map is loaded into object_map. |
- template <typename LabelType> |
void JumpIfNotString(Register object, |
Register object_map, |
- LabelType* not_string); |
+ Label* not_string, |
+ Label::Distance near_jump = Label::kFar); |
- template <typename LabelType> |
- void JumpIfNotBothSequentialAsciiStrings(Register first_object, |
- Register second_object, |
- Register scratch1, |
- Register scratch2, |
- LabelType* on_not_both_flat_ascii); |
+ void JumpIfNotBothSequentialAsciiStrings( |
+ Register first_object, |
+ Register second_object, |
+ Register scratch1, |
+ Register scratch2, |
+ Label* on_not_both_flat_ascii, |
+ Label::Distance near_jump = Label::kFar); |
// Check whether the instance type represents a flat ascii string. Jump to the |
// label if not. If the instance type can be scratched specify same register |
// for both instance type and scratch. |
- template <typename LabelType> |
void JumpIfInstanceTypeIsNotSequentialAscii( |
Register instance_type, |
Register scratch, |
- LabelType *on_not_flat_ascii_string); |
+ Label*on_not_flat_ascii_string, |
+ Label::Distance near_jump = Label::kFar); |
- template <typename LabelType> |
void JumpIfBothInstanceTypesAreNotSequentialAscii( |
Register first_object_instance_type, |
Register second_object_instance_type, |
Register scratch1, |
Register scratch2, |
- LabelType* on_fail); |
+ Label* on_fail, |
+ Label::Distance near_jump = Label::kFar); |
// --------------------------------------------------------------------------- |
// Macro instructions. |
@@ -1103,6 +1107,7 @@ class MacroAssembler: public Assembler { |
// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. |
static int kSafepointPushRegisterIndices[Register::kNumRegisters]; |
static const int kNumSafepointSavedRegisters = 11; |
+ static const int kSmiShift = kSmiTagSize + kSmiShiftSize; |
bool generating_stub_; |
bool allow_stub_calls_; |
@@ -1119,14 +1124,14 @@ class MacroAssembler: public Assembler { |
Handle<Object> code_object_; |
// Helper functions for generating invokes. |
- template <typename LabelType> |
void InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, |
Handle<Code> code_constant, |
Register code_register, |
- LabelType* done, |
+ Label* done, |
InvokeFlag flag, |
- const CallWrapper& call_wrapper); |
+ const CallWrapper& call_wrapper, |
+ Label::Distance near_jump = Label::kFar); |
// Activation support. |
void EnterFrame(StackFrame::Type type); |
@@ -1252,750 +1257,6 @@ extern void LogGeneratedCodeCoverage(const char* file_line); |
#define ACCESS_MASM(masm) masm-> |
#endif |
-// ----------------------------------------------------------------------------- |
-// Template implementations. |
- |
-static int kSmiShift = kSmiTagSize + kSmiShiftSize; |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiNeg(Register dst, |
- Register src, |
- LabelType* on_smi_result) { |
- if (dst.is(src)) { |
- ASSERT(!dst.is(kScratchRegister)); |
- movq(kScratchRegister, src); |
- neg(dst); // Low 32 bits are retained as zero by negation. |
- // Test if result is zero or Smi::kMinValue. |
- cmpq(dst, kScratchRegister); |
- j(not_equal, on_smi_result); |
- movq(src, kScratchRegister); |
- } else { |
- movq(dst, src); |
- neg(dst); |
- cmpq(dst, src); |
- // If the result is zero or Smi::kMinValue, negation failed to create a smi. |
- j(not_equal, on_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiAdd(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT_NOT_NULL(on_not_smi_result); |
- ASSERT(!dst.is(src2)); |
- if (dst.is(src1)) { |
- movq(kScratchRegister, src1); |
- addq(kScratchRegister, src2); |
- j(overflow, on_not_smi_result); |
- movq(dst, kScratchRegister); |
- } else { |
- movq(dst, src1); |
- addq(dst, src2); |
- j(overflow, on_not_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiAdd(Register dst, |
- Register src1, |
- const Operand& src2, |
- LabelType* on_not_smi_result) { |
- ASSERT_NOT_NULL(on_not_smi_result); |
- if (dst.is(src1)) { |
- movq(kScratchRegister, src1); |
- addq(kScratchRegister, src2); |
- j(overflow, on_not_smi_result); |
- movq(dst, kScratchRegister); |
- } else { |
- ASSERT(!src2.AddressUsesRegister(dst)); |
- movq(dst, src1); |
- addq(dst, src2); |
- j(overflow, on_not_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiSub(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT_NOT_NULL(on_not_smi_result); |
- ASSERT(!dst.is(src2)); |
- if (dst.is(src1)) { |
- cmpq(dst, src2); |
- j(overflow, on_not_smi_result); |
- subq(dst, src2); |
- } else { |
- movq(dst, src1); |
- subq(dst, src2); |
- j(overflow, on_not_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiSub(Register dst, |
- Register src1, |
- const Operand& src2, |
- LabelType* on_not_smi_result) { |
- ASSERT_NOT_NULL(on_not_smi_result); |
- if (dst.is(src1)) { |
- movq(kScratchRegister, src2); |
- cmpq(src1, kScratchRegister); |
- j(overflow, on_not_smi_result); |
- subq(src1, kScratchRegister); |
- } else { |
- movq(dst, src1); |
- subq(dst, src2); |
- j(overflow, on_not_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiMul(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT(!dst.is(src2)); |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- |
- if (dst.is(src1)) { |
- Label failure, zero_correct_result; |
- movq(kScratchRegister, src1); // Create backup for later testing. |
- SmiToInteger64(dst, src1); |
- imul(dst, src2); |
- j(overflow, &failure, Label::kNear); |
- |
- // Check for negative zero result. If product is zero, and one |
- // argument is negative, go to slow case. |
- Label correct_result; |
- testq(dst, dst); |
- j(not_zero, &correct_result, Label::kNear); |
- |
- movq(dst, kScratchRegister); |
- xor_(dst, src2); |
- // Result was positive zero. |
- j(positive, &zero_correct_result, Label::kNear); |
- |
- bind(&failure); // Reused failure exit, restores src1. |
- movq(src1, kScratchRegister); |
- jmp(on_not_smi_result); |
- |
- bind(&zero_correct_result); |
- Set(dst, 0); |
- |
- bind(&correct_result); |
- } else { |
- SmiToInteger64(dst, src1); |
- imul(dst, src2); |
- j(overflow, on_not_smi_result); |
- // Check for negative zero result. If product is zero, and one |
- // argument is negative, go to slow case. |
- Label correct_result; |
- testq(dst, dst); |
- j(not_zero, &correct_result, Label::kNear); |
- // One of src1 and src2 is zero, the check whether the other is |
- // negative. |
- movq(kScratchRegister, src1); |
- xor_(kScratchRegister, src2); |
- j(negative, on_not_smi_result); |
- bind(&correct_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiTryAddConstant(Register dst, |
- Register src, |
- Smi* constant, |
- LabelType* on_not_smi_result) { |
- // Does not assume that src is a smi. |
- ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask)); |
- ASSERT_EQ(0, kSmiTag); |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src.is(kScratchRegister)); |
- |
- JumpIfNotSmi(src, on_not_smi_result); |
- Register tmp = (dst.is(src) ? kScratchRegister : dst); |
- LoadSmiConstant(tmp, constant); |
- addq(tmp, src); |
- j(overflow, on_not_smi_result); |
- if (dst.is(src)) { |
- movq(dst, tmp); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiAddConstant(Register dst, |
- Register src, |
- Smi* constant, |
- LabelType* on_not_smi_result) { |
- if (constant->value() == 0) { |
- if (!dst.is(src)) { |
- movq(dst, src); |
- } |
- } else if (dst.is(src)) { |
- ASSERT(!dst.is(kScratchRegister)); |
- |
- LoadSmiConstant(kScratchRegister, constant); |
- addq(kScratchRegister, src); |
- j(overflow, on_not_smi_result); |
- movq(dst, kScratchRegister); |
- } else { |
- LoadSmiConstant(dst, constant); |
- addq(dst, src); |
- j(overflow, on_not_smi_result); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiSubConstant(Register dst, |
- Register src, |
- Smi* constant, |
- LabelType* on_not_smi_result) { |
- if (constant->value() == 0) { |
- if (!dst.is(src)) { |
- movq(dst, src); |
- } |
- } else if (dst.is(src)) { |
- ASSERT(!dst.is(kScratchRegister)); |
- if (constant->value() == Smi::kMinValue) { |
- // Subtracting min-value from any non-negative value will overflow. |
- // We test the non-negativeness before doing the subtraction. |
- testq(src, src); |
- j(not_sign, on_not_smi_result); |
- LoadSmiConstant(kScratchRegister, constant); |
- subq(dst, kScratchRegister); |
- } else { |
- // Subtract by adding the negation. |
- LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); |
- addq(kScratchRegister, dst); |
- j(overflow, on_not_smi_result); |
- movq(dst, kScratchRegister); |
- } |
- } else { |
- if (constant->value() == Smi::kMinValue) { |
- // Subtracting min-value from any non-negative value will overflow. |
- // We test the non-negativeness before doing the subtraction. |
- testq(src, src); |
- j(not_sign, on_not_smi_result); |
- LoadSmiConstant(dst, constant); |
- // Adding and subtracting the min-value gives the same result, it only |
- // differs on the overflow bit, which we don't check here. |
- addq(dst, src); |
- } else { |
- // Subtract by adding the negation. |
- LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); |
- addq(dst, src); |
- j(overflow, on_not_smi_result); |
- } |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiDiv(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src2.is(rax)); |
- ASSERT(!src2.is(rdx)); |
- ASSERT(!src1.is(rdx)); |
- |
- // Check for 0 divisor (result is +/-Infinity). |
- testq(src2, src2); |
- j(zero, on_not_smi_result); |
- |
- if (src1.is(rax)) { |
- movq(kScratchRegister, src1); |
- } |
- SmiToInteger32(rax, src1); |
- // We need to rule out dividing Smi::kMinValue by -1, since that would |
- // overflow in idiv and raise an exception. |
- // We combine this with negative zero test (negative zero only happens |
- // when dividing zero by a negative number). |
- |
- // We overshoot a little and go to slow case if we divide min-value |
- // by any negative value, not just -1. |
- Label safe_div; |
- testl(rax, Immediate(0x7fffffff)); |
- j(not_zero, &safe_div, Label::kNear); |
- testq(src2, src2); |
- if (src1.is(rax)) { |
- j(positive, &safe_div, Label::kNear); |
- movq(src1, kScratchRegister); |
- jmp(on_not_smi_result); |
- } else { |
- j(negative, on_not_smi_result); |
- } |
- bind(&safe_div); |
- |
- SmiToInteger32(src2, src2); |
- // Sign extend src1 into edx:eax. |
- cdq(); |
- idivl(src2); |
- Integer32ToSmi(src2, src2); |
- // Check that the remainder is zero. |
- testl(rdx, rdx); |
- if (src1.is(rax)) { |
- Label smi_result; |
- j(zero, &smi_result, Label::kNear); |
- movq(src1, kScratchRegister); |
- jmp(on_not_smi_result); |
- bind(&smi_result); |
- } else { |
- j(not_zero, on_not_smi_result); |
- } |
- if (!dst.is(src1) && src1.is(rax)) { |
- movq(src1, kScratchRegister); |
- } |
- Integer32ToSmi(dst, rax); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiMod(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- ASSERT(!src2.is(rax)); |
- ASSERT(!src2.is(rdx)); |
- ASSERT(!src1.is(rdx)); |
- ASSERT(!src1.is(src2)); |
- |
- testq(src2, src2); |
- j(zero, on_not_smi_result); |
- |
- if (src1.is(rax)) { |
- movq(kScratchRegister, src1); |
- } |
- SmiToInteger32(rax, src1); |
- SmiToInteger32(src2, src2); |
- |
- // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). |
- Label safe_div; |
- cmpl(rax, Immediate(Smi::kMinValue)); |
- j(not_equal, &safe_div, Label::kNear); |
- cmpl(src2, Immediate(-1)); |
- j(not_equal, &safe_div, Label::kNear); |
- // Retag inputs and go slow case. |
- Integer32ToSmi(src2, src2); |
- if (src1.is(rax)) { |
- movq(src1, kScratchRegister); |
- } |
- jmp(on_not_smi_result); |
- bind(&safe_div); |
- |
- // Sign extend eax into edx:eax. |
- cdq(); |
- idivl(src2); |
- // Restore smi tags on inputs. |
- Integer32ToSmi(src2, src2); |
- if (src1.is(rax)) { |
- movq(src1, kScratchRegister); |
- } |
- // Check for a negative zero result. If the result is zero, and the |
- // dividend is negative, go slow to return a floating point negative zero. |
- Label smi_result; |
- testl(rdx, rdx); |
- j(not_zero, &smi_result, Label::kNear); |
- testq(src1, src1); |
- j(negative, on_not_smi_result); |
- bind(&smi_result); |
- Integer32ToSmi(dst, rdx); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiShiftLogicalRightConstant( |
- Register dst, Register src, int shift_value, LabelType* on_not_smi_result) { |
- // Logic right shift interprets its result as an *unsigned* number. |
- if (dst.is(src)) { |
- UNIMPLEMENTED(); // Not used. |
- } else { |
- movq(dst, src); |
- if (shift_value == 0) { |
- testq(dst, dst); |
- j(negative, on_not_smi_result); |
- } |
- shr(dst, Immediate(shift_value + kSmiShift)); |
- shl(dst, Immediate(kSmiShift)); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiShiftLogicalRight(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smi_result) { |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- ASSERT(!dst.is(rcx)); |
- // dst and src1 can be the same, because the one case that bails out |
- // is a shift by 0, which leaves dst, and therefore src1, unchanged. |
- if (src1.is(rcx) || src2.is(rcx)) { |
- movq(kScratchRegister, rcx); |
- } |
- if (!dst.is(src1)) { |
- movq(dst, src1); |
- } |
- SmiToInteger32(rcx, src2); |
- orl(rcx, Immediate(kSmiShift)); |
- shr_cl(dst); // Shift is rcx modulo 0x1f + 32. |
- shl(dst, Immediate(kSmiShift)); |
- testq(dst, dst); |
- if (src1.is(rcx) || src2.is(rcx)) { |
- Label positive_result; |
- j(positive, &positive_result, Label::kNear); |
- if (src1.is(rcx)) { |
- movq(src1, kScratchRegister); |
- } else { |
- movq(src2, kScratchRegister); |
- } |
- jmp(on_not_smi_result); |
- bind(&positive_result); |
- } else { |
- j(negative, on_not_smi_result); // src2 was zero and src1 negative. |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SelectNonSmi(Register dst, |
- Register src1, |
- Register src2, |
- LabelType* on_not_smis) { |
- ASSERT(!dst.is(kScratchRegister)); |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- ASSERT(!dst.is(src1)); |
- ASSERT(!dst.is(src2)); |
- // Both operands must not be smis. |
-#ifdef DEBUG |
- if (allow_stub_calls()) { // Check contains a stub call. |
- Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); |
- Check(not_both_smis, "Both registers were smis in SelectNonSmi."); |
- } |
-#endif |
- ASSERT_EQ(0, kSmiTag); |
- ASSERT_EQ(0, Smi::FromInt(0)); |
- movl(kScratchRegister, Immediate(kSmiTagMask)); |
- and_(kScratchRegister, src1); |
- testl(kScratchRegister, src2); |
- // If non-zero then both are smis. |
- j(not_zero, on_not_smis); |
- |
- // Exactly one operand is a smi. |
- ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); |
- // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. |
- subq(kScratchRegister, Immediate(1)); |
- // If src1 is a smi, then scratch register all 1s, else it is all 0s. |
- movq(dst, src1); |
- xor_(dst, src2); |
- and_(dst, kScratchRegister); |
- // If src1 is a smi, dst holds src1 ^ src2, else it is zero. |
- xor_(dst, src1); |
- // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfSmi(Register src, LabelType* on_smi) { |
- ASSERT_EQ(0, kSmiTag); |
- Condition smi = CheckSmi(src); |
- j(smi, on_smi); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfNotSmi(Register src, LabelType* on_not_smi) { |
- Condition smi = CheckSmi(src); |
- j(NegateCondition(smi), on_not_smi); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpUnlessNonNegativeSmi( |
- Register src, LabelType* on_not_smi_or_negative) { |
- Condition non_negative_smi = CheckNonNegativeSmi(src); |
- j(NegateCondition(non_negative_smi), on_not_smi_or_negative); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfSmiEqualsConstant(Register src, |
- Smi* constant, |
- LabelType* on_equals) { |
- SmiCompare(src, constant); |
- j(equal, on_equals); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfNotValidSmiValue(Register src, |
- LabelType* on_invalid) { |
- Condition is_valid = CheckInteger32ValidSmiValue(src); |
- j(NegateCondition(is_valid), on_invalid); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfUIntNotValidSmiValue(Register src, |
- LabelType* on_invalid) { |
- Condition is_valid = CheckUInteger32ValidSmiValue(src); |
- j(NegateCondition(is_valid), on_invalid); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfNotBothSmi(Register src1, |
- Register src2, |
- LabelType* on_not_both_smi) { |
- Condition both_smi = CheckBothSmi(src1, src2); |
- j(NegateCondition(both_smi), on_not_both_smi); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1, |
- Register src2, |
- LabelType* on_not_both_smi) { |
- Condition both_smi = CheckBothNonNegativeSmi(src1, src2); |
- j(NegateCondition(both_smi), on_not_both_smi); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2, |
- LabelType* on_not_smis) { |
- if (dst.is(src1) || dst.is(src2)) { |
- ASSERT(!src1.is(kScratchRegister)); |
- ASSERT(!src2.is(kScratchRegister)); |
- movq(kScratchRegister, src1); |
- or_(kScratchRegister, src2); |
- JumpIfNotSmi(kScratchRegister, on_not_smis); |
- movq(dst, kScratchRegister); |
- } else { |
- movq(dst, src1); |
- or_(dst, src2); |
- JumpIfNotSmi(dst, on_not_smis); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfNotString(Register object, |
- Register object_map, |
- LabelType* not_string) { |
- Condition is_smi = CheckSmi(object); |
- j(is_smi, not_string); |
- CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map); |
- j(above_equal, not_string); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object, |
- Register second_object, |
- Register scratch1, |
- Register scratch2, |
- LabelType* on_fail) { |
- // Check that both objects are not smis. |
- Condition either_smi = CheckEitherSmi(first_object, second_object); |
- j(either_smi, on_fail); |
- |
- // Load instance type for both strings. |
- movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset)); |
- movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset)); |
- movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); |
- movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); |
- |
- // Check that both are flat ascii strings. |
- ASSERT(kNotStringTag != 0); |
- const int kFlatAsciiStringMask = |
- kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
- const int kFlatAsciiStringTag = ASCII_STRING_TYPE; |
- |
- andl(scratch1, Immediate(kFlatAsciiStringMask)); |
- andl(scratch2, Immediate(kFlatAsciiStringMask)); |
- // Interleave the bits to check both scratch1 and scratch2 in one test. |
- ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); |
- lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
- cmpl(scratch1, |
- Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); |
- j(not_equal, on_fail); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( |
- Register instance_type, |
- Register scratch, |
- LabelType *failure) { |
- if (!scratch.is(instance_type)) { |
- movl(scratch, instance_type); |
- } |
- |
- const int kFlatAsciiStringMask = |
- kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
- |
- andl(scratch, Immediate(kFlatAsciiStringMask)); |
- cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); |
- j(not_equal, failure); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( |
- Register first_object_instance_type, |
- Register second_object_instance_type, |
- Register scratch1, |
- Register scratch2, |
- LabelType* on_fail) { |
- // Load instance type for both strings. |
- movq(scratch1, first_object_instance_type); |
- movq(scratch2, second_object_instance_type); |
- |
- // Check that both are flat ascii strings. |
- ASSERT(kNotStringTag != 0); |
- const int kFlatAsciiStringMask = |
- kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
- const int kFlatAsciiStringTag = ASCII_STRING_TYPE; |
- |
- andl(scratch1, Immediate(kFlatAsciiStringMask)); |
- andl(scratch2, Immediate(kFlatAsciiStringMask)); |
- // Interleave the bits to check both scratch1 and scratch2 in one test. |
- ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); |
- lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); |
- cmpl(scratch1, |
- Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3))); |
- j(not_equal, on_fail); |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::InNewSpace(Register object, |
- Register scratch, |
- Condition cc, |
- LabelType* branch) { |
- if (Serializer::enabled()) { |
- // Can't do arithmetic on external references if it might get serialized. |
- // The mask isn't really an address. We load it as an external reference in |
- // case the size of the new space is different between the snapshot maker |
- // and the running system. |
- if (scratch.is(object)) { |
- movq(kScratchRegister, ExternalReference::new_space_mask(isolate())); |
- and_(scratch, kScratchRegister); |
- } else { |
- movq(scratch, ExternalReference::new_space_mask(isolate())); |
- and_(scratch, object); |
- } |
- movq(kScratchRegister, ExternalReference::new_space_start(isolate())); |
- cmpq(scratch, kScratchRegister); |
- j(cc, branch); |
- } else { |
- ASSERT(is_int32(static_cast<int64_t>(HEAP->NewSpaceMask()))); |
- intptr_t new_space_start = |
- reinterpret_cast<intptr_t>(HEAP->NewSpaceStart()); |
- movq(kScratchRegister, -new_space_start, RelocInfo::NONE); |
- if (scratch.is(object)) { |
- addq(scratch, kScratchRegister); |
- } else { |
- lea(scratch, Operand(object, kScratchRegister, times_1, 0)); |
- } |
- and_(scratch, Immediate(static_cast<int32_t>(HEAP->NewSpaceMask()))); |
- j(cc, branch); |
- } |
-} |
- |
- |
-template <typename LabelType> |
-void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
- const ParameterCount& actual, |
- Handle<Code> code_constant, |
- Register code_register, |
- LabelType* done, |
- InvokeFlag flag, |
- const CallWrapper& call_wrapper) { |
- bool definitely_matches = false; |
- Label invoke; |
- if (expected.is_immediate()) { |
- ASSERT(actual.is_immediate()); |
- if (expected.immediate() == actual.immediate()) { |
- definitely_matches = true; |
- } else { |
- Set(rax, actual.immediate()); |
- if (expected.immediate() == |
- SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
- // Don't worry about adapting arguments for built-ins that |
- // don't want that done. Skip adaption code by making it look |
- // like we have a match between expected and actual number of |
- // arguments. |
- definitely_matches = true; |
- } else { |
- Set(rbx, expected.immediate()); |
- } |
- } |
- } else { |
- if (actual.is_immediate()) { |
- // Expected is in register, actual is immediate. This is the |
- // case when we invoke function values without going through the |
- // IC mechanism. |
- cmpq(expected.reg(), Immediate(actual.immediate())); |
- j(equal, &invoke, Label::kNear); |
- ASSERT(expected.reg().is(rbx)); |
- Set(rax, actual.immediate()); |
- } else if (!expected.reg().is(actual.reg())) { |
- // Both expected and actual are in (different) registers. This |
- // is the case when we invoke functions using call and apply. |
- cmpq(expected.reg(), actual.reg()); |
- j(equal, &invoke, Label::kNear); |
- ASSERT(actual.reg().is(rax)); |
- ASSERT(expected.reg().is(rbx)); |
- } |
- } |
- |
- if (!definitely_matches) { |
- Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
- if (!code_constant.is_null()) { |
- movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
- addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
- } else if (!code_register.is(rdx)) { |
- movq(rdx, code_register); |
- } |
- |
- if (flag == CALL_FUNCTION) { |
- call_wrapper.BeforeCall(CallSize(adaptor)); |
- Call(adaptor, RelocInfo::CODE_TARGET); |
- call_wrapper.AfterCall(); |
- jmp(done); |
- } else { |
- Jump(adaptor, RelocInfo::CODE_TARGET); |
- } |
- bind(&invoke); |
- } |
-} |
- |
- |
} } // namespace v8::internal |
#endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |