Out-of-line constant pool on Arm: Stage 1 - Free up r7 for use as constant pool pointer register
First stage of implementing an out-of-line constant pool on Arm. This CL frees up register r7 for use as a constant pool pointer in later stages. BUG= R=ulan@chromium.org Review URL: https://chromiumcodereview.appspot.com/21063002 Patch from Ross McIlroy <rmcilroy@chromium.org>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16898 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c47cc38b12
commit
b99802f50c
@ -118,7 +118,8 @@ class CpuFeatures : public AllStatic {
|
|||||||
// Core register
|
// Core register
|
||||||
struct Register {
|
struct Register {
|
||||||
static const int kNumRegisters = 16;
|
static const int kNumRegisters = 16;
|
||||||
static const int kMaxNumAllocatableRegisters = 8;
|
static const int kMaxNumAllocatableRegisters =
|
||||||
|
FLAG_enable_ool_constant_pool ? 7 : 8;
|
||||||
static const int kSizeInBytes = 4;
|
static const int kSizeInBytes = 4;
|
||||||
|
|
||||||
inline static int NumAllocatableRegisters();
|
inline static int NumAllocatableRegisters();
|
||||||
@ -201,6 +202,7 @@ const Register r3 = { kRegister_r3_Code };
|
|||||||
const Register r4 = { kRegister_r4_Code };
|
const Register r4 = { kRegister_r4_Code };
|
||||||
const Register r5 = { kRegister_r5_Code };
|
const Register r5 = { kRegister_r5_Code };
|
||||||
const Register r6 = { kRegister_r6_Code };
|
const Register r6 = { kRegister_r6_Code };
|
||||||
|
// Used as constant pool pointer register if FLAGS_enable_ool_constant_pool.
|
||||||
const Register r7 = { kRegister_r7_Code };
|
const Register r7 = { kRegister_r7_Code };
|
||||||
// Used as context register.
|
// Used as context register.
|
||||||
const Register r8 = { kRegister_r8_Code };
|
const Register r8 = { kRegister_r8_Code };
|
||||||
|
@ -445,9 +445,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|||||||
// r3: object size (in words)
|
// r3: object size (in words)
|
||||||
// r4: JSObject (not tagged)
|
// r4: JSObject (not tagged)
|
||||||
// r5: First in-object property of JSObject (not tagged)
|
// r5: First in-object property of JSObject (not tagged)
|
||||||
__ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
|
|
||||||
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
|
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
|
||||||
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
|
||||||
if (count_constructions) {
|
if (count_constructions) {
|
||||||
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
|
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
|
||||||
__ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
|
__ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
|
||||||
@ -455,14 +454,16 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|||||||
__ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
|
__ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
|
||||||
// r0: offset of first field after pre-allocated fields
|
// r0: offset of first field after pre-allocated fields
|
||||||
if (FLAG_debug_code) {
|
if (FLAG_debug_code) {
|
||||||
__ cmp(r0, r6);
|
__ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
|
||||||
|
__ cmp(r0, ip);
|
||||||
__ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
|
__ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
|
||||||
}
|
}
|
||||||
__ InitializeFieldsWithFiller(r5, r0, r7);
|
__ InitializeFieldsWithFiller(r5, r0, r6);
|
||||||
// To allow for truncation.
|
// To allow for truncation.
|
||||||
__ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
|
__ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
|
||||||
}
|
}
|
||||||
__ InitializeFieldsWithFiller(r5, r6, r7);
|
__ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
|
||||||
|
__ InitializeFieldsWithFiller(r5, r0, r6);
|
||||||
|
|
||||||
// Add the object tag to make the JSObject real, so that we can continue
|
// Add the object tag to make the JSObject real, so that we can continue
|
||||||
// and jump into the continuation code at any time from now on. Any
|
// and jump into the continuation code at any time from now on. Any
|
||||||
@ -527,16 +528,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|||||||
__ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
|
__ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
|
||||||
ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
|
ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
|
||||||
{ Label loop, entry;
|
{ Label loop, entry;
|
||||||
if (count_constructions) {
|
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||||
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
|
|
||||||
} else if (FLAG_debug_code) {
|
|
||||||
__ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
|
|
||||||
__ cmp(r7, r8);
|
|
||||||
__ Assert(eq, kUndefinedValueNotLoaded);
|
|
||||||
}
|
|
||||||
__ b(&entry);
|
__ b(&entry);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
__ str(r7, MemOperand(r2, kPointerSize, PostIndex));
|
__ str(r0, MemOperand(r2, kPointerSize, PostIndex));
|
||||||
__ bind(&entry);
|
__ bind(&entry);
|
||||||
__ cmp(r2, r6);
|
__ cmp(r2, r6);
|
||||||
__ b(lt, &loop);
|
__ b(lt, &loop);
|
||||||
@ -700,7 +695,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
|||||||
// r2: receiver
|
// r2: receiver
|
||||||
// r3: argc
|
// r3: argc
|
||||||
// r4: argv
|
// r4: argv
|
||||||
// r5-r7, cp may be clobbered
|
// r5-r6, r7 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered
|
||||||
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
||||||
|
|
||||||
// Clear the context before we push it when entering the internal frame.
|
// Clear the context before we push it when entering the internal frame.
|
||||||
@ -740,7 +735,9 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
|||||||
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
|
||||||
__ mov(r5, Operand(r4));
|
__ mov(r5, Operand(r4));
|
||||||
__ mov(r6, Operand(r4));
|
__ mov(r6, Operand(r4));
|
||||||
__ mov(r7, Operand(r4));
|
if (!FLAG_enable_ool_constant_pool) {
|
||||||
|
__ mov(r7, Operand(r4));
|
||||||
|
}
|
||||||
if (kR9Available == 1) {
|
if (kR9Available == 1) {
|
||||||
__ mov(r9, Operand(r4));
|
__ mov(r9, Operand(r4));
|
||||||
}
|
}
|
||||||
|
@ -825,8 +825,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
|||||||
// Convert lhs to a double in d7.
|
// Convert lhs to a double in d7.
|
||||||
__ SmiToDouble(d7, lhs);
|
__ SmiToDouble(d7, lhs);
|
||||||
// Load the double from rhs, tagged HeapNumber r0, to d6.
|
// Load the double from rhs, tagged HeapNumber r0, to d6.
|
||||||
__ sub(r7, rhs, Operand(kHeapObjectTag));
|
__ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
|
||||||
__ vldr(d6, r7, HeapNumber::kValueOffset);
|
|
||||||
|
|
||||||
// We now have both loaded as doubles but we can skip the lhs nan check
|
// We now have both loaded as doubles but we can skip the lhs nan check
|
||||||
// since it's a smi.
|
// since it's a smi.
|
||||||
@ -851,8 +850,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Rhs is a smi, lhs is a heap number.
|
// Rhs is a smi, lhs is a heap number.
|
||||||
// Load the double from lhs, tagged HeapNumber r1, to d7.
|
// Load the double from lhs, tagged HeapNumber r1, to d7.
|
||||||
__ sub(r7, lhs, Operand(kHeapObjectTag));
|
__ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
|
||||||
__ vldr(d7, r7, HeapNumber::kValueOffset);
|
|
||||||
// Convert rhs to a double in d6 .
|
// Convert rhs to a double in d6 .
|
||||||
__ SmiToDouble(d6, rhs);
|
__ SmiToDouble(d6, rhs);
|
||||||
// Fall through to both_loaded_as_doubles.
|
// Fall through to both_loaded_as_doubles.
|
||||||
@ -920,10 +918,8 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Both are heap numbers. Load them up then jump to the code we have
|
// Both are heap numbers. Load them up then jump to the code we have
|
||||||
// for that.
|
// for that.
|
||||||
__ sub(r7, rhs, Operand(kHeapObjectTag));
|
__ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
|
||||||
__ vldr(d6, r7, HeapNumber::kValueOffset);
|
__ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
|
||||||
__ sub(r7, lhs, Operand(kHeapObjectTag));
|
|
||||||
__ vldr(d7, r7, HeapNumber::kValueOffset);
|
|
||||||
__ jmp(both_loaded_as_doubles);
|
__ jmp(both_loaded_as_doubles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1267,13 +1263,14 @@ void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
|||||||
|
|
||||||
|
|
||||||
void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
|
void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
|
||||||
Token::Value op) {
|
Token::Value op,
|
||||||
|
Register scratch1,
|
||||||
|
Register scratch2) {
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r7;
|
|
||||||
Register scratch2 = r9;
|
|
||||||
|
|
||||||
ASSERT(right.is(r0));
|
ASSERT(right.is(r0));
|
||||||
|
ASSERT(!AreAliased(left, right, scratch1, scratch2, ip));
|
||||||
STATIC_ASSERT(kSmiTag == 0);
|
STATIC_ASSERT(kSmiTag == 0);
|
||||||
|
|
||||||
Label not_smi_result;
|
Label not_smi_result;
|
||||||
@ -1488,11 +1485,15 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
|||||||
Label* gc_required,
|
Label* gc_required,
|
||||||
Label* miss,
|
Label* miss,
|
||||||
Token::Value op,
|
Token::Value op,
|
||||||
OverwriteMode mode) {
|
OverwriteMode mode,
|
||||||
|
Register scratch1,
|
||||||
|
Register scratch2,
|
||||||
|
Register scratch3,
|
||||||
|
Register scratch4) {
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r6;
|
Register result = scratch3;
|
||||||
Register scratch2 = r7;
|
ASSERT(!AreAliased(left, right, scratch1, scratch2, scratch3, scratch4));
|
||||||
|
|
||||||
ASSERT(smi_operands || (not_numbers != NULL));
|
ASSERT(smi_operands || (not_numbers != NULL));
|
||||||
if (smi_operands) {
|
if (smi_operands) {
|
||||||
@ -1506,7 +1507,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
|||||||
__ JumpIfNotSmi(right, miss);
|
__ JumpIfNotSmi(right, miss);
|
||||||
}
|
}
|
||||||
|
|
||||||
Register heap_number_map = r9;
|
Register heap_number_map = scratch4;
|
||||||
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -1516,7 +1517,6 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
|||||||
case Token::DIV:
|
case Token::DIV:
|
||||||
case Token::MOD: {
|
case Token::MOD: {
|
||||||
// Allocate new heap number for result.
|
// Allocate new heap number for result.
|
||||||
Register result = r5;
|
|
||||||
BinaryOpStub_GenerateHeapResultAllocation(
|
BinaryOpStub_GenerateHeapResultAllocation(
|
||||||
masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
|
masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
|
||||||
|
|
||||||
@ -1635,7 +1635,6 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Allocate new heap number for result.
|
// Allocate new heap number for result.
|
||||||
__ bind(&result_not_a_smi);
|
__ bind(&result_not_a_smi);
|
||||||
Register result = r5;
|
|
||||||
if (smi_operands) {
|
if (smi_operands) {
|
||||||
__ AllocateHeapNumber(
|
__ AllocateHeapNumber(
|
||||||
result, scratch1, scratch2, heap_number_map, gc_required);
|
result, scratch1, scratch2, heap_number_map, gc_required);
|
||||||
@ -1646,11 +1645,11 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// r2: Answer as signed int32.
|
// r2: Answer as signed int32.
|
||||||
// r5: Heap number to write answer into.
|
// result: Heap number to write answer into.
|
||||||
|
|
||||||
// Nothing can go wrong now, so move the heap number to r0, which is the
|
// Nothing can go wrong now, so move the heap number to r0, which is the
|
||||||
// result.
|
// result.
|
||||||
__ mov(r0, Operand(r5));
|
__ mov(r0, Operand(result));
|
||||||
|
|
||||||
// Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
|
// Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
|
||||||
// mentioned above SHR needs to always produce a positive result.
|
// mentioned above SHR needs to always produce a positive result.
|
||||||
@ -1681,26 +1680,31 @@ void BinaryOpStub_GenerateSmiCode(
|
|||||||
Label* gc_required,
|
Label* gc_required,
|
||||||
Token::Value op,
|
Token::Value op,
|
||||||
BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
|
BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
|
||||||
OverwriteMode mode) {
|
OverwriteMode mode,
|
||||||
|
Register scratch1,
|
||||||
|
Register scratch2,
|
||||||
|
Register scratch3,
|
||||||
|
Register scratch4) {
|
||||||
Label not_smis;
|
Label not_smis;
|
||||||
|
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r7;
|
ASSERT(!AreAliased(left, right, scratch1, scratch2, scratch3, scratch4));
|
||||||
|
|
||||||
// Perform combined smi check on both operands.
|
// Perform combined smi check on both operands.
|
||||||
__ orr(scratch1, left, Operand(right));
|
__ orr(scratch1, left, Operand(right));
|
||||||
__ JumpIfNotSmi(scratch1, ¬_smis);
|
__ JumpIfNotSmi(scratch1, ¬_smis);
|
||||||
|
|
||||||
// If the smi-smi operation results in a smi return is generated.
|
// If the smi-smi operation results in a smi return is generated.
|
||||||
BinaryOpStub_GenerateSmiSmiOperation(masm, op);
|
BinaryOpStub_GenerateSmiSmiOperation(masm, op, scratch1, scratch2);
|
||||||
|
|
||||||
// If heap number results are possible generate the result in an allocated
|
// If heap number results are possible generate the result in an allocated
|
||||||
// heap number.
|
// heap number.
|
||||||
if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
|
if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
|
||||||
BinaryOpStub_GenerateFPOperation(
|
BinaryOpStub_GenerateFPOperation(
|
||||||
masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
|
masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
|
||||||
use_runtime, gc_required, ¬_smis, op, mode);
|
use_runtime, gc_required, ¬_smis, op, mode, scratch2, scratch3,
|
||||||
|
scratch1, scratch4);
|
||||||
}
|
}
|
||||||
__ bind(¬_smis);
|
__ bind(¬_smis);
|
||||||
}
|
}
|
||||||
@ -1719,14 +1723,13 @@ void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
||||||
result_type_ == BinaryOpIC::SMI) {
|
result_type_ == BinaryOpIC::SMI) {
|
||||||
// Only allow smi results.
|
// Only allow smi results.
|
||||||
BinaryOpStub_GenerateSmiCode(
|
BinaryOpStub_GenerateSmiCode(masm, &call_runtime, NULL, op_,
|
||||||
masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_);
|
NO_HEAPNUMBER_RESULTS, mode_, r5, r6, r4, r9);
|
||||||
} else {
|
} else {
|
||||||
// Allow heap number result and don't make a transition if a heap number
|
// Allow heap number result and don't make a transition if a heap number
|
||||||
// cannot be allocated.
|
// cannot be allocated.
|
||||||
BinaryOpStub_GenerateSmiCode(
|
BinaryOpStub_GenerateSmiCode(masm, &call_runtime, &call_runtime, op_,
|
||||||
masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS,
|
ALLOW_HEAPNUMBER_RESULTS, mode_, r5, r6, r4, r9);
|
||||||
mode_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code falls through if the result is not returned as either a smi or heap
|
// Code falls through if the result is not returned as either a smi or heap
|
||||||
@ -1780,8 +1783,9 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
|
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r7;
|
Register scratch1 = r4;
|
||||||
Register scratch2 = r9;
|
Register scratch2 = r9;
|
||||||
|
Register scratch3 = r5;
|
||||||
LowDwVfpRegister double_scratch = d0;
|
LowDwVfpRegister double_scratch = d0;
|
||||||
|
|
||||||
Register heap_number_result = no_reg;
|
Register heap_number_result = no_reg;
|
||||||
@ -1798,7 +1802,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
Label skip;
|
Label skip;
|
||||||
__ orr(scratch1, left, right);
|
__ orr(scratch1, left, right);
|
||||||
__ JumpIfNotSmi(scratch1, &skip);
|
__ JumpIfNotSmi(scratch1, &skip);
|
||||||
BinaryOpStub_GenerateSmiSmiOperation(masm, op_);
|
BinaryOpStub_GenerateSmiSmiOperation(masm, op_, scratch2, scratch3);
|
||||||
// Fall through if the result is not a smi.
|
// Fall through if the result is not a smi.
|
||||||
__ bind(&skip);
|
__ bind(&skip);
|
||||||
|
|
||||||
@ -1892,12 +1896,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
__ b(ne, &transition);
|
__ b(ne, &transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We preserved r0 and r1 to be able to call runtime.
|
|
||||||
// Save the left value on the stack.
|
|
||||||
__ Push(r5, r4);
|
|
||||||
|
|
||||||
Label pop_and_call_runtime;
|
|
||||||
|
|
||||||
// Allocate a heap number to store the result.
|
// Allocate a heap number to store the result.
|
||||||
heap_number_result = r5;
|
heap_number_result = r5;
|
||||||
BinaryOpStub_GenerateHeapResultAllocation(masm,
|
BinaryOpStub_GenerateHeapResultAllocation(masm,
|
||||||
@ -1905,20 +1903,15 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
heap_number_map,
|
heap_number_map,
|
||||||
scratch1,
|
scratch1,
|
||||||
scratch2,
|
scratch2,
|
||||||
&pop_and_call_runtime,
|
&call_runtime,
|
||||||
mode_);
|
mode_);
|
||||||
|
|
||||||
// Load the left value from the value saved on the stack.
|
|
||||||
__ Pop(r1, r0);
|
|
||||||
|
|
||||||
// Call the C function to handle the double operation.
|
// Call the C function to handle the double operation.
|
||||||
CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
|
CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
|
||||||
if (FLAG_debug_code) {
|
if (FLAG_debug_code) {
|
||||||
__ stop("Unreachable code.");
|
__ stop("Unreachable code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
__ bind(&pop_and_call_runtime);
|
|
||||||
__ Drop(2);
|
|
||||||
__ b(&call_runtime);
|
__ b(&call_runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2069,7 +2062,7 @@ void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
|||||||
Label call_runtime, transition;
|
Label call_runtime, transition;
|
||||||
BinaryOpStub_GenerateFPOperation(
|
BinaryOpStub_GenerateFPOperation(
|
||||||
masm, left_type_, right_type_, false,
|
masm, left_type_, right_type_, false,
|
||||||
&transition, &call_runtime, &transition, op_, mode_);
|
&transition, &call_runtime, &transition, op_, mode_, r6, r4, r5, r9);
|
||||||
|
|
||||||
__ bind(&transition);
|
__ bind(&transition);
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
@ -2088,11 +2081,13 @@ void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
Label call_runtime, call_string_add_or_runtime, transition;
|
Label call_runtime, call_string_add_or_runtime, transition;
|
||||||
|
|
||||||
BinaryOpStub_GenerateSmiCode(
|
BinaryOpStub_GenerateSmiCode(
|
||||||
masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_);
|
masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_,
|
||||||
|
r5, r6, r4, r9);
|
||||||
|
|
||||||
BinaryOpStub_GenerateFPOperation(
|
BinaryOpStub_GenerateFPOperation(
|
||||||
masm, left_type_, right_type_, false,
|
masm, left_type_, right_type_, false,
|
||||||
&call_string_add_or_runtime, &call_runtime, &transition, op_, mode_);
|
&call_string_add_or_runtime, &call_runtime, &transition, op_, mode_, r6,
|
||||||
|
r4, r5, r9);
|
||||||
|
|
||||||
__ bind(&transition);
|
__ bind(&transition);
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
@ -2194,7 +2189,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
|||||||
Label calculate;
|
Label calculate;
|
||||||
Label invalid_cache;
|
Label invalid_cache;
|
||||||
const Register scratch0 = r9;
|
const Register scratch0 = r9;
|
||||||
const Register scratch1 = r7;
|
Register scratch1 = no_reg; // will be r4
|
||||||
const Register cache_entry = r0;
|
const Register cache_entry = r0;
|
||||||
const bool tagged = (argument_type_ == TAGGED);
|
const bool tagged = (argument_type_ == TAGGED);
|
||||||
|
|
||||||
@ -2274,6 +2269,9 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
|||||||
__ cmp(r2, r4);
|
__ cmp(r2, r4);
|
||||||
__ cmp(r3, r5, eq);
|
__ cmp(r3, r5, eq);
|
||||||
__ b(ne, &calculate);
|
__ b(ne, &calculate);
|
||||||
|
|
||||||
|
scratch1 = r4; // Start of scratch1 range.
|
||||||
|
|
||||||
// Cache hit. Load result, cleanup and return.
|
// Cache hit. Load result, cleanup and return.
|
||||||
Counters* counters = masm->isolate()->counters();
|
Counters* counters = masm->isolate()->counters();
|
||||||
__ IncrementCounter(
|
__ IncrementCounter(
|
||||||
@ -2416,7 +2414,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
|||||||
const DwVfpRegister double_scratch = d0;
|
const DwVfpRegister double_scratch = d0;
|
||||||
const SwVfpRegister single_scratch = s0;
|
const SwVfpRegister single_scratch = s0;
|
||||||
const Register scratch = r9;
|
const Register scratch = r9;
|
||||||
const Register scratch2 = r7;
|
const Register scratch2 = r4;
|
||||||
|
|
||||||
Label call_runtime, done, int_exponent;
|
Label call_runtime, done, int_exponent;
|
||||||
if (exponent_type_ == ON_STACK) {
|
if (exponent_type_ == ON_STACK) {
|
||||||
@ -2926,14 +2924,14 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|||||||
// r3: argc
|
// r3: argc
|
||||||
// r4: argv
|
// r4: argv
|
||||||
Isolate* isolate = masm->isolate();
|
Isolate* isolate = masm->isolate();
|
||||||
__ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used.
|
|
||||||
int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
|
int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
|
||||||
__ mov(r7, Operand(Smi::FromInt(marker)));
|
__ mov(r8, Operand(Smi::FromInt(marker)));
|
||||||
__ mov(r6, Operand(Smi::FromInt(marker)));
|
__ mov(r6, Operand(Smi::FromInt(marker)));
|
||||||
__ mov(r5,
|
__ mov(r5,
|
||||||
Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
|
Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
|
||||||
__ ldr(r5, MemOperand(r5));
|
__ ldr(r5, MemOperand(r5));
|
||||||
__ Push(r8, r7, r6, r5);
|
__ mov(ip, Operand(-1)); // Push a bad frame pointer to fail if it is used.
|
||||||
|
__ Push(ip, r8, r6, r5);
|
||||||
|
|
||||||
// Set up frame pointer for the frame to be pushed.
|
// Set up frame pointer for the frame to be pushed.
|
||||||
__ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
|
__ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
|
||||||
@ -2979,7 +2977,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
|||||||
// Invoke: Link this frame into the handler chain. There's only one
|
// Invoke: Link this frame into the handler chain. There's only one
|
||||||
// handler block in this code object, so its index is 0.
|
// handler block in this code object, so its index is 0.
|
||||||
__ bind(&invoke);
|
__ bind(&invoke);
|
||||||
// Must preserve r0-r4, r5-r7 are available.
|
// Must preserve r0-r4, r5-r6 are available.
|
||||||
__ PushTryHandler(StackHandler::JS_ENTRY, 0);
|
__ PushTryHandler(StackHandler::JS_ENTRY, 0);
|
||||||
// If an exception not caught by another handler occurs, this handler
|
// If an exception not caught by another handler occurs, this handler
|
||||||
// returns control to the code after the bl(&invoke) above, which
|
// returns control to the code after the bl(&invoke) above, which
|
||||||
@ -3586,31 +3584,36 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
|
|||||||
__ ldr(r9, MemOperand(sp, 0 * kPointerSize));
|
__ ldr(r9, MemOperand(sp, 0 * kPointerSize));
|
||||||
__ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
|
__ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
|
||||||
__ sub(r9, r9, Operand(r1));
|
__ sub(r9, r9, Operand(r1));
|
||||||
__ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
|
__ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
|
||||||
__ add(r3, r4, Operand(r6, LSL, 1));
|
__ add(r3, r4, Operand(r6, LSL, 1));
|
||||||
__ add(r3, r3, Operand(kParameterMapHeaderSize));
|
__ add(r3, r3, Operand(kParameterMapHeaderSize));
|
||||||
|
|
||||||
// r6 = loop variable (tagged)
|
// r6 = loop variable (tagged)
|
||||||
// r1 = mapping index (tagged)
|
// r1 = mapping index (tagged)
|
||||||
// r3 = address of backing store (tagged)
|
// r3 = address of backing store (tagged)
|
||||||
// r4 = address of parameter map (tagged)
|
// r4 = address of parameter map (tagged), which is also the address of new
|
||||||
// r5 = temporary scratch (a.o., for address calculation)
|
// object + Heap::kArgumentsObjectSize (tagged)
|
||||||
// r7 = the hole value
|
// r0 = temporary scratch (a.o., for address calculation)
|
||||||
|
// r5 = the hole value
|
||||||
__ jmp(¶meters_test);
|
__ jmp(¶meters_test);
|
||||||
|
|
||||||
__ bind(¶meters_loop);
|
__ bind(¶meters_loop);
|
||||||
__ sub(r6, r6, Operand(Smi::FromInt(1)));
|
__ sub(r6, r6, Operand(Smi::FromInt(1)));
|
||||||
__ mov(r5, Operand(r6, LSL, 1));
|
__ mov(r0, Operand(r6, LSL, 1));
|
||||||
__ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag));
|
__ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
|
||||||
__ str(r9, MemOperand(r4, r5));
|
__ str(r9, MemOperand(r4, r0));
|
||||||
__ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
|
__ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
|
||||||
__ str(r7, MemOperand(r3, r5));
|
__ str(r5, MemOperand(r3, r0));
|
||||||
__ add(r9, r9, Operand(Smi::FromInt(1)));
|
__ add(r9, r9, Operand(Smi::FromInt(1)));
|
||||||
__ bind(¶meters_test);
|
__ bind(¶meters_test);
|
||||||
__ cmp(r6, Operand(Smi::FromInt(0)));
|
__ cmp(r6, Operand(Smi::FromInt(0)));
|
||||||
__ b(ne, ¶meters_loop);
|
__ b(ne, ¶meters_loop);
|
||||||
|
|
||||||
|
// Restore r0 = new object (tagged)
|
||||||
|
__ sub(r0, r4, Operand(Heap::kArgumentsObjectSize));
|
||||||
|
|
||||||
__ bind(&skip_parameter_map);
|
__ bind(&skip_parameter_map);
|
||||||
|
// r0 = address of new object (tagged)
|
||||||
// r2 = argument count (tagged)
|
// r2 = argument count (tagged)
|
||||||
// r3 = address of backing store (tagged)
|
// r3 = address of backing store (tagged)
|
||||||
// r5 = scratch
|
// r5 = scratch
|
||||||
@ -3641,6 +3644,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
|
|||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
// Do the runtime call to allocate the arguments object.
|
// Do the runtime call to allocate the arguments object.
|
||||||
|
// r0 = address of new object (tagged)
|
||||||
// r2 = argument count (tagged)
|
// r2 = argument count (tagged)
|
||||||
__ bind(&runtime);
|
__ bind(&runtime);
|
||||||
__ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
|
__ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
|
||||||
@ -3769,7 +3773,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
// therefore the content of these registers are safe to use after the call.
|
// therefore the content of these registers are safe to use after the call.
|
||||||
Register subject = r4;
|
Register subject = r4;
|
||||||
Register regexp_data = r5;
|
Register regexp_data = r5;
|
||||||
Register last_match_info_elements = r6;
|
Register last_match_info_elements = no_reg; // will be r6;
|
||||||
|
|
||||||
// Ensure that a RegExp stack is allocated.
|
// Ensure that a RegExp stack is allocated.
|
||||||
Isolate* isolate = masm->isolate();
|
Isolate* isolate = masm->isolate();
|
||||||
@ -3902,19 +3906,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
__ and_(r0, r0, Operand(kStringEncodingMask));
|
__ and_(r0, r0, Operand(kStringEncodingMask));
|
||||||
__ mov(r3, Operand(r0, ASR, 2), SetCC);
|
__ mov(r3, Operand(r0, ASR, 2), SetCC);
|
||||||
__ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
|
__ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
|
||||||
__ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
|
__ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
|
||||||
|
|
||||||
// (E) Carry on. String handling is done.
|
// (E) Carry on. String handling is done.
|
||||||
// r7: irregexp code
|
// r6: irregexp code
|
||||||
// Check that the irregexp code has been generated for the actual string
|
// Check that the irregexp code has been generated for the actual string
|
||||||
// encoding. If it has, the field contains a code object otherwise it contains
|
// encoding. If it has, the field contains a code object otherwise it contains
|
||||||
// a smi (code flushing support).
|
// a smi (code flushing support).
|
||||||
__ JumpIfSmi(r7, &runtime);
|
__ JumpIfSmi(r6, &runtime);
|
||||||
|
|
||||||
// r1: previous index
|
// r1: previous index
|
||||||
// r3: encoding of subject string (1 if ASCII, 0 if two_byte);
|
// r3: encoding of subject string (1 if ASCII, 0 if two_byte);
|
||||||
// r7: code
|
// r6: code
|
||||||
// subject: Subject string
|
// subject: Subject string
|
||||||
// regexp_data: RegExp data (FixedArray)
|
// regexp_data: RegExp data (FixedArray)
|
||||||
// All checks done. Now push arguments for native regexp code.
|
// All checks done. Now push arguments for native regexp code.
|
||||||
@ -3981,12 +3985,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ mov(r0, subject);
|
__ mov(r0, subject);
|
||||||
|
|
||||||
// Locate the code entry and call it.
|
// Locate the code entry and call it.
|
||||||
__ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
|
__ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||||
DirectCEntryStub stub;
|
DirectCEntryStub stub;
|
||||||
stub.GenerateCall(masm, r7);
|
stub.GenerateCall(masm, r6);
|
||||||
|
|
||||||
__ LeaveExitFrame(false, no_reg, true);
|
__ LeaveExitFrame(false, no_reg, true);
|
||||||
|
|
||||||
|
last_match_info_elements = r6;
|
||||||
|
|
||||||
// r0: result
|
// r0: result
|
||||||
// subject: subject string (callee saved)
|
// subject: subject string (callee saved)
|
||||||
// regexp_data: RegExp data (callee saved)
|
// regexp_data: RegExp data (callee saved)
|
||||||
@ -4075,7 +4081,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ RecordWriteField(last_match_info_elements,
|
__ RecordWriteField(last_match_info_elements,
|
||||||
RegExpImpl::kLastSubjectOffset,
|
RegExpImpl::kLastSubjectOffset,
|
||||||
subject,
|
subject,
|
||||||
r7,
|
r3,
|
||||||
kLRHasNotBeenSaved,
|
kLRHasNotBeenSaved,
|
||||||
kDontSaveFPRegs);
|
kDontSaveFPRegs);
|
||||||
__ mov(subject, r2);
|
__ mov(subject, r2);
|
||||||
@ -4085,7 +4091,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ RecordWriteField(last_match_info_elements,
|
__ RecordWriteField(last_match_info_elements,
|
||||||
RegExpImpl::kLastInputOffset,
|
RegExpImpl::kLastInputOffset,
|
||||||
subject,
|
subject,
|
||||||
r7,
|
r3,
|
||||||
kLRHasNotBeenSaved,
|
kLRHasNotBeenSaved,
|
||||||
kDontSaveFPRegs);
|
kDontSaveFPRegs);
|
||||||
|
|
||||||
@ -4652,7 +4658,6 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
|
|||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Register scratch4,
|
Register scratch4,
|
||||||
Register scratch5,
|
|
||||||
int flags) {
|
int flags) {
|
||||||
bool ascii = (flags & COPY_ASCII) != 0;
|
bool ascii = (flags & COPY_ASCII) != 0;
|
||||||
bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
|
bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
|
||||||
@ -4727,30 +4732,29 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
|
|||||||
|
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
__ ldr(scratch3, MemOperand(src, 4, PostIndex));
|
__ ldr(scratch3, MemOperand(src, 4, PostIndex));
|
||||||
__ sub(scratch5, limit, Operand(dest));
|
|
||||||
__ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift));
|
__ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift));
|
||||||
__ str(scratch1, MemOperand(dest, 4, PostIndex));
|
__ str(scratch1, MemOperand(dest, 4, PostIndex));
|
||||||
__ mov(scratch1, Operand(scratch3, LSR, right_shift));
|
__ mov(scratch1, Operand(scratch3, LSR, right_shift));
|
||||||
// Loop if four or more bytes left to copy.
|
// Loop if four or more bytes left to copy.
|
||||||
// Compare to eight, because we did the subtract before increasing dst.
|
__ sub(scratch3, limit, Operand(dest));
|
||||||
__ sub(scratch5, scratch5, Operand(8), SetCC);
|
__ sub(scratch3, scratch3, Operand(4), SetCC);
|
||||||
__ b(ge, &loop);
|
__ b(ge, &loop);
|
||||||
}
|
}
|
||||||
// There is now between zero and three bytes left to copy (negative that
|
// There is now between zero and three bytes left to copy (negative that
|
||||||
// number is in scratch5), and between one and three bytes already read into
|
// number is in scratch3), and between one and three bytes already read into
|
||||||
// scratch1 (eight times that number in scratch4). We may have read past
|
// scratch1 (eight times that number in scratch4). We may have read past
|
||||||
// the end of the string, but because objects are aligned, we have not read
|
// the end of the string, but because objects are aligned, we have not read
|
||||||
// past the end of the object.
|
// past the end of the object.
|
||||||
// Find the minimum of remaining characters to move and preloaded characters
|
// Find the minimum of remaining characters to move and preloaded characters
|
||||||
// and write those as bytes.
|
// and write those as bytes.
|
||||||
__ add(scratch5, scratch5, Operand(4), SetCC);
|
__ add(scratch3, scratch3, Operand(4), SetCC);
|
||||||
__ b(eq, &done);
|
__ b(eq, &done);
|
||||||
__ cmp(scratch4, Operand(scratch5, LSL, 3), ne);
|
__ cmp(scratch4, Operand(scratch3, LSL, 3), ne);
|
||||||
// Move minimum of bytes read and bytes left to copy to scratch4.
|
// Move minimum of bytes read and bytes left to copy to scratch4.
|
||||||
__ mov(scratch5, Operand(scratch4, LSR, 3), LeaveCC, lt);
|
__ mov(scratch3, Operand(scratch4, LSR, 3), LeaveCC, lt);
|
||||||
// Between one and three (value in scratch5) characters already read into
|
// Between one and three (value in scratch3) characters already read into
|
||||||
// scratch ready to write.
|
// scratch ready to write.
|
||||||
__ cmp(scratch5, Operand(2));
|
__ cmp(scratch3, Operand(2));
|
||||||
__ strb(scratch1, MemOperand(dest, 1, PostIndex));
|
__ strb(scratch1, MemOperand(dest, 1, PostIndex));
|
||||||
__ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge);
|
__ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge);
|
||||||
__ strb(scratch1, MemOperand(dest, 1, PostIndex), ge);
|
__ strb(scratch1, MemOperand(dest, 1, PostIndex), ge);
|
||||||
@ -5090,10 +5094,10 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||||
__ tst(r1, Operand(kStringEncodingMask));
|
__ tst(r1, Operand(kStringEncodingMask));
|
||||||
__ b(eq, &two_byte_slice);
|
__ b(eq, &two_byte_slice);
|
||||||
__ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime);
|
__ AllocateAsciiSlicedString(r0, r2, r6, r4, &runtime);
|
||||||
__ jmp(&set_slice_header);
|
__ jmp(&set_slice_header);
|
||||||
__ bind(&two_byte_slice);
|
__ bind(&two_byte_slice);
|
||||||
__ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime);
|
__ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime);
|
||||||
__ bind(&set_slice_header);
|
__ bind(&set_slice_header);
|
||||||
__ mov(r3, Operand(r3, LSL, 1));
|
__ mov(r3, Operand(r3, LSL, 1));
|
||||||
__ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
|
__ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
|
||||||
@ -5134,7 +5138,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|||||||
__ b(eq, &two_byte_sequential);
|
__ b(eq, &two_byte_sequential);
|
||||||
|
|
||||||
// Allocate and copy the resulting ASCII string.
|
// Allocate and copy the resulting ASCII string.
|
||||||
__ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime);
|
__ AllocateAsciiString(r0, r2, r4, r6, r1, &runtime);
|
||||||
|
|
||||||
// Locate first character of substring to copy.
|
// Locate first character of substring to copy.
|
||||||
__ add(r5, r5, r3);
|
__ add(r5, r5, r3);
|
||||||
@ -5146,13 +5150,13 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|||||||
// r2: result string length
|
// r2: result string length
|
||||||
// r5: first character of substring to copy
|
// r5: first character of substring to copy
|
||||||
STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
||||||
StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
|
StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r9,
|
||||||
COPY_ASCII | DEST_ALWAYS_ALIGNED);
|
COPY_ASCII | DEST_ALWAYS_ALIGNED);
|
||||||
__ jmp(&return_r0);
|
__ jmp(&return_r0);
|
||||||
|
|
||||||
// Allocate and copy the resulting two-byte string.
|
// Allocate and copy the resulting two-byte string.
|
||||||
__ bind(&two_byte_sequential);
|
__ bind(&two_byte_sequential);
|
||||||
__ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime);
|
__ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime);
|
||||||
|
|
||||||
// Locate first character of substring to copy.
|
// Locate first character of substring to copy.
|
||||||
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
|
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
|
||||||
@ -5166,7 +5170,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
|||||||
// r5: first character of substring to copy.
|
// r5: first character of substring to copy.
|
||||||
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
|
||||||
StringHelper::GenerateCopyCharactersLong(
|
StringHelper::GenerateCopyCharactersLong(
|
||||||
masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
|
masm, r1, r5, r2, r3, r4, r6, r9, DEST_ALWAYS_ALIGNED);
|
||||||
|
|
||||||
__ bind(&return_r0);
|
__ bind(&return_r0);
|
||||||
Counters* counters = masm->isolate()->counters();
|
Counters* counters = masm->isolate()->counters();
|
||||||
@ -5432,7 +5436,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
__ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
|
__ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
|
||||||
__ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
|
__ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
|
||||||
}
|
}
|
||||||
__ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
|
__ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r3,
|
||||||
&call_runtime);
|
&call_runtime);
|
||||||
|
|
||||||
// Get the two characters forming the sub string.
|
// Get the two characters forming the sub string.
|
||||||
@ -5443,7 +5447,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
// just allocate a new one.
|
// just allocate a new one.
|
||||||
Label make_two_character_string;
|
Label make_two_character_string;
|
||||||
StringHelper::GenerateTwoCharacterStringTableProbe(
|
StringHelper::GenerateTwoCharacterStringTableProbe(
|
||||||
masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
|
masm, r2, r3, r6, r0, r4, r5, r9, &make_two_character_string);
|
||||||
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
||||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
@ -5488,7 +5492,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Allocate an ASCII cons string.
|
// Allocate an ASCII cons string.
|
||||||
__ bind(&ascii_data);
|
__ bind(&ascii_data);
|
||||||
__ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime);
|
__ AllocateAsciiConsString(r3, r6, r4, r5, &call_runtime);
|
||||||
__ bind(&allocated);
|
__ bind(&allocated);
|
||||||
// Fill the fields of the cons string.
|
// Fill the fields of the cons string.
|
||||||
Label skip_write_barrier, after_writing;
|
Label skip_write_barrier, after_writing;
|
||||||
@ -5499,15 +5503,15 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
__ cmp(r4, Operand::Zero());
|
__ cmp(r4, Operand::Zero());
|
||||||
__ b(eq, &skip_write_barrier);
|
__ b(eq, &skip_write_barrier);
|
||||||
|
|
||||||
__ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
|
__ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
|
||||||
__ RecordWriteField(r7,
|
__ RecordWriteField(r3,
|
||||||
ConsString::kFirstOffset,
|
ConsString::kFirstOffset,
|
||||||
r0,
|
r0,
|
||||||
r4,
|
r4,
|
||||||
kLRHasNotBeenSaved,
|
kLRHasNotBeenSaved,
|
||||||
kDontSaveFPRegs);
|
kDontSaveFPRegs);
|
||||||
__ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
|
__ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
|
||||||
__ RecordWriteField(r7,
|
__ RecordWriteField(r3,
|
||||||
ConsString::kSecondOffset,
|
ConsString::kSecondOffset,
|
||||||
r1,
|
r1,
|
||||||
r4,
|
r4,
|
||||||
@ -5516,12 +5520,12 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
__ jmp(&after_writing);
|
__ jmp(&after_writing);
|
||||||
|
|
||||||
__ bind(&skip_write_barrier);
|
__ bind(&skip_write_barrier);
|
||||||
__ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
|
__ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
|
||||||
__ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
|
__ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
|
||||||
|
|
||||||
__ bind(&after_writing);
|
__ bind(&after_writing);
|
||||||
|
|
||||||
__ mov(r0, Operand(r7));
|
__ mov(r0, Operand(r3));
|
||||||
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
||||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
@ -5541,7 +5545,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
__ b(eq, &ascii_data);
|
__ b(eq, &ascii_data);
|
||||||
|
|
||||||
// Allocate a two byte cons string.
|
// Allocate a two byte cons string.
|
||||||
__ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime);
|
__ AllocateTwoByteConsString(r3, r6, r4, r5, &call_runtime);
|
||||||
__ jmp(&allocated);
|
__ jmp(&allocated);
|
||||||
|
|
||||||
// We cannot encounter sliced strings or cons strings here since:
|
// We cannot encounter sliced strings or cons strings here since:
|
||||||
@ -5565,14 +5569,15 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check whether both strings have same encoding
|
// Check whether both strings have same encoding
|
||||||
__ eor(r7, r4, Operand(r5));
|
__ eor(ip, r4, Operand(r5));
|
||||||
__ tst(r7, Operand(kStringEncodingMask));
|
ASSERT(__ ImmediateFitsAddrMode1Instruction(kStringEncodingMask));
|
||||||
|
__ tst(ip, Operand(kStringEncodingMask));
|
||||||
__ b(ne, &call_runtime);
|
__ b(ne, &call_runtime);
|
||||||
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
STATIC_ASSERT(kSeqStringTag == 0);
|
||||||
__ tst(r4, Operand(kStringRepresentationMask));
|
__ tst(r4, Operand(kStringRepresentationMask));
|
||||||
STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
|
STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
|
||||||
__ add(r7,
|
__ add(r6,
|
||||||
r0,
|
r0,
|
||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
|
||||||
LeaveCC,
|
LeaveCC,
|
||||||
@ -5582,7 +5587,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||||
__ tst(r4, Operand(kShortExternalStringMask));
|
__ tst(r4, Operand(kShortExternalStringMask));
|
||||||
__ b(ne, &call_runtime);
|
__ b(ne, &call_runtime);
|
||||||
__ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
|
__ ldr(r6, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
|
||||||
__ bind(&first_prepared);
|
__ bind(&first_prepared);
|
||||||
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
STATIC_ASSERT(kSeqStringTag == 0);
|
||||||
@ -5602,43 +5607,46 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
|||||||
__ bind(&second_prepared);
|
__ bind(&second_prepared);
|
||||||
|
|
||||||
Label non_ascii_string_add_flat_result;
|
Label non_ascii_string_add_flat_result;
|
||||||
// r7: first character of first string
|
// r6: first character of first string
|
||||||
// r1: first character of second string
|
// r1: first character of second string
|
||||||
// r2: length of first string.
|
// r2: length of first string.
|
||||||
// r3: length of second string.
|
// r3: length of second string.
|
||||||
// r6: sum of lengths.
|
|
||||||
// Both strings have the same encoding.
|
// Both strings have the same encoding.
|
||||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
__ tst(r5, Operand(kStringEncodingMask));
|
__ tst(r5, Operand(kStringEncodingMask));
|
||||||
__ b(eq, &non_ascii_string_add_flat_result);
|
__ b(eq, &non_ascii_string_add_flat_result);
|
||||||
|
|
||||||
__ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime);
|
__ add(r2, r2, Operand(r3));
|
||||||
__ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
__ AllocateAsciiString(r0, r2, r4, r5, r9, &call_runtime);
|
||||||
|
__ sub(r2, r2, Operand(r3));
|
||||||
|
__ add(r5, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
// r0: result string.
|
// r0: result string.
|
||||||
// r7: first character of first string.
|
// r6: first character of first string.
|
||||||
// r1: first character of second string.
|
// r1: first character of second string.
|
||||||
// r2: length of first string.
|
// r2: length of first string.
|
||||||
// r3: length of second string.
|
// r3: length of second string.
|
||||||
// r6: first character of result.
|
// r5: first character of result.
|
||||||
StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true);
|
StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, true);
|
||||||
// r6: next character of result.
|
// r5: next character of result.
|
||||||
StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
|
StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, true);
|
||||||
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
||||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
__ bind(&non_ascii_string_add_flat_result);
|
__ bind(&non_ascii_string_add_flat_result);
|
||||||
__ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime);
|
__ add(r2, r2, Operand(r3));
|
||||||
__ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
__ AllocateTwoByteString(r0, r2, r4, r5, r9, &call_runtime);
|
||||||
|
__ sub(r2, r2, Operand(r3));
|
||||||
|
__ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
// r0: result string.
|
// r0: result string.
|
||||||
// r7: first character of first string.
|
// r6: first character of first string.
|
||||||
// r1: first character of second string.
|
// r1: first character of second string.
|
||||||
// r2: length of first string.
|
// r2: length of first string.
|
||||||
// r3: length of second string.
|
// r3: length of second string.
|
||||||
// r6: first character of result.
|
// r5: first character of result.
|
||||||
StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false);
|
StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, false);
|
||||||
// r6: next character of result.
|
// r5: next character of result.
|
||||||
StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
|
StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, false);
|
||||||
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
||||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
@ -6308,7 +6316,7 @@ struct AheadOfTimeWriteBarrierStubList {
|
|||||||
|
|
||||||
static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
||||||
// Used in RegExpExecStub.
|
// Used in RegExpExecStub.
|
||||||
{ REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET },
|
{ REG(r6), REG(r4), REG(r3), EMIT_REMEMBERED_SET },
|
||||||
// Used in CompileArrayPushCall.
|
// Used in CompileArrayPushCall.
|
||||||
// Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
|
// Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
|
||||||
// Also used in KeyedStoreIC::GenerateGeneric.
|
// Also used in KeyedStoreIC::GenerateGeneric.
|
||||||
@ -6335,8 +6343,8 @@ static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
|||||||
// FastNewClosureStub::Generate
|
// FastNewClosureStub::Generate
|
||||||
{ REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET },
|
{ REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET },
|
||||||
// StringAddStub::Generate
|
// StringAddStub::Generate
|
||||||
{ REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
|
{ REG(r3), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
|
||||||
{ REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
|
{ REG(r3), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
|
||||||
// Null termination.
|
// Null termination.
|
||||||
{ REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
|
{ REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
|
||||||
};
|
};
|
||||||
|
@ -106,7 +106,6 @@ class StringHelper : public AllStatic {
|
|||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Register scratch4,
|
Register scratch4,
|
||||||
Register scratch5,
|
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
|
|
||||||
|
@ -444,15 +444,16 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
|
|||||||
|
|
||||||
__ push(lr);
|
__ push(lr);
|
||||||
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
|
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
|
||||||
// r4: source FixedArray
|
|
||||||
// r5: number of elements (smi-tagged)
|
// r5: number of elements (smi-tagged)
|
||||||
|
|
||||||
// Allocate new FixedDoubleArray.
|
// Allocate new FixedDoubleArray.
|
||||||
// Use lr as a temporary register.
|
// Use lr as a temporary register.
|
||||||
__ mov(lr, Operand(r5, LSL, 2));
|
__ mov(lr, Operand(r5, LSL, 2));
|
||||||
__ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
|
__ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
|
||||||
__ Allocate(lr, r6, r7, r9, &gc_required, DOUBLE_ALIGNMENT);
|
__ Allocate(lr, r6, r4, r9, &gc_required, DOUBLE_ALIGNMENT);
|
||||||
// r6: destination FixedDoubleArray, not tagged as heap object.
|
// r6: destination FixedDoubleArray, not tagged as heap object.
|
||||||
|
__ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
|
||||||
|
// r4: source FixedArray.
|
||||||
|
|
||||||
// Set destination FixedDoubleArray's length and map.
|
// Set destination FixedDoubleArray's length and map.
|
||||||
__ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
|
__ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
|
||||||
@ -483,15 +484,15 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
|
|||||||
|
|
||||||
// Prepare for conversion loop.
|
// Prepare for conversion loop.
|
||||||
__ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
__ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
||||||
__ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize));
|
__ add(r9, r6, Operand(FixedDoubleArray::kHeaderSize));
|
||||||
__ add(r6, r7, Operand(r5, LSL, 2));
|
__ add(r6, r9, Operand(r5, LSL, 2));
|
||||||
__ mov(r4, Operand(kHoleNanLower32));
|
__ mov(r4, Operand(kHoleNanLower32));
|
||||||
__ mov(r5, Operand(kHoleNanUpper32));
|
__ mov(r5, Operand(kHoleNanUpper32));
|
||||||
// r3: begin of source FixedArray element fields, not tagged
|
// r3: begin of source FixedArray element fields, not tagged
|
||||||
// r4: kHoleNanLower32
|
// r4: kHoleNanLower32
|
||||||
// r5: kHoleNanUpper32
|
// r5: kHoleNanUpper32
|
||||||
// r6: end of destination FixedDoubleArray, not tagged
|
// r6: end of destination FixedDoubleArray, not tagged
|
||||||
// r7: begin of FixedDoubleArray element fields, not tagged
|
// r9: begin of FixedDoubleArray element fields, not tagged
|
||||||
|
|
||||||
__ b(&entry);
|
__ b(&entry);
|
||||||
|
|
||||||
@ -514,30 +515,30 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
|
|||||||
|
|
||||||
// Convert and copy elements.
|
// Convert and copy elements.
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
__ ldr(r9, MemOperand(r3, 4, PostIndex));
|
__ ldr(lr, MemOperand(r3, 4, PostIndex));
|
||||||
// r9: current element
|
// lr: current element
|
||||||
__ UntagAndJumpIfNotSmi(r9, r9, &convert_hole);
|
__ UntagAndJumpIfNotSmi(lr, lr, &convert_hole);
|
||||||
|
|
||||||
// Normal smi, convert to double and store.
|
// Normal smi, convert to double and store.
|
||||||
__ vmov(s0, r9);
|
__ vmov(s0, lr);
|
||||||
__ vcvt_f64_s32(d0, s0);
|
__ vcvt_f64_s32(d0, s0);
|
||||||
__ vstr(d0, r7, 0);
|
__ vstr(d0, r9, 0);
|
||||||
__ add(r7, r7, Operand(8));
|
__ add(r9, r9, Operand(8));
|
||||||
__ b(&entry);
|
__ b(&entry);
|
||||||
|
|
||||||
// Hole found, store the-hole NaN.
|
// Hole found, store the-hole NaN.
|
||||||
__ bind(&convert_hole);
|
__ bind(&convert_hole);
|
||||||
if (FLAG_debug_code) {
|
if (FLAG_debug_code) {
|
||||||
// Restore a "smi-untagged" heap object.
|
// Restore a "smi-untagged" heap object.
|
||||||
__ SmiTag(r9);
|
__ SmiTag(lr);
|
||||||
__ orr(r9, r9, Operand(1));
|
__ orr(lr, lr, Operand(1));
|
||||||
__ CompareRoot(r9, Heap::kTheHoleValueRootIndex);
|
__ CompareRoot(lr, Heap::kTheHoleValueRootIndex);
|
||||||
__ Assert(eq, kObjectFoundInSmiOnlyArray);
|
__ Assert(eq, kObjectFoundInSmiOnlyArray);
|
||||||
}
|
}
|
||||||
__ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
|
__ Strd(r4, r5, MemOperand(r9, 8, PostIndex));
|
||||||
|
|
||||||
__ bind(&entry);
|
__ bind(&entry);
|
||||||
__ cmp(r7, r6);
|
__ cmp(r9, r6);
|
||||||
__ b(lt, &loop);
|
__ b(lt, &loop);
|
||||||
|
|
||||||
__ pop(lr);
|
__ pop(lr);
|
||||||
@ -577,7 +578,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
|||||||
// Allocate new FixedArray.
|
// Allocate new FixedArray.
|
||||||
__ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
|
__ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
|
||||||
__ add(r0, r0, Operand(r5, LSL, 1));
|
__ add(r0, r0, Operand(r5, LSL, 1));
|
||||||
__ Allocate(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
|
__ Allocate(r0, r6, r3, r9, &gc_required, NO_ALLOCATION_FLAGS);
|
||||||
// r6: destination FixedArray, not tagged as heap object
|
// r6: destination FixedArray, not tagged as heap object
|
||||||
// Set destination FixedDoubleArray's length and map.
|
// Set destination FixedDoubleArray's length and map.
|
||||||
__ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
|
__ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
|
||||||
@ -589,14 +590,12 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
|||||||
__ add(r3, r6, Operand(FixedArray::kHeaderSize));
|
__ add(r3, r6, Operand(FixedArray::kHeaderSize));
|
||||||
__ add(r6, r6, Operand(kHeapObjectTag));
|
__ add(r6, r6, Operand(kHeapObjectTag));
|
||||||
__ add(r5, r3, Operand(r5, LSL, 1));
|
__ add(r5, r3, Operand(r5, LSL, 1));
|
||||||
__ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
|
|
||||||
__ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
|
||||||
// Using offsetted addresses in r4 to fully take advantage of post-indexing.
|
// Using offsetted addresses in r4 to fully take advantage of post-indexing.
|
||||||
// r3: begin of destination FixedArray element fields, not tagged
|
// r3: begin of destination FixedArray element fields, not tagged
|
||||||
// r4: begin of source FixedDoubleArray element fields, not tagged, +4
|
// r4: begin of source FixedDoubleArray element fields, not tagged, +4
|
||||||
// r5: end of destination FixedArray, not tagged
|
// r5: end of destination FixedArray, not tagged
|
||||||
// r6: destination FixedArray
|
// r6: destination FixedArray
|
||||||
// r7: the-hole pointer
|
|
||||||
// r9: heap number map
|
// r9: heap number map
|
||||||
__ b(&entry);
|
__ b(&entry);
|
||||||
|
|
||||||
@ -608,7 +607,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
|||||||
|
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
__ ldr(r1, MemOperand(r4, 8, PostIndex));
|
__ ldr(r1, MemOperand(r4, 8, PostIndex));
|
||||||
// lr: current element's upper 32 bit
|
// r1: current element's upper 32 bit
|
||||||
// r4: address of next element's upper 32 bit
|
// r4: address of next element's upper 32 bit
|
||||||
__ cmp(r1, Operand(kHoleNanUpper32));
|
__ cmp(r1, Operand(kHoleNanUpper32));
|
||||||
__ b(eq, &convert_hole);
|
__ b(eq, &convert_hole);
|
||||||
@ -631,7 +630,8 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
|||||||
|
|
||||||
// Replace the-hole NaN with the-hole pointer.
|
// Replace the-hole NaN with the-hole pointer.
|
||||||
__ bind(&convert_hole);
|
__ bind(&convert_hole);
|
||||||
__ str(r7, MemOperand(r3, 4, PostIndex));
|
__ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
|
||||||
|
__ str(r0, MemOperand(r3, 4, PostIndex));
|
||||||
|
|
||||||
__ bind(&entry);
|
__ bind(&entry);
|
||||||
__ cmp(r3, r5);
|
__ cmp(r3, r5);
|
||||||
|
@ -268,8 +268,8 @@ void Deoptimizer::EntryGenerator::Generate() {
|
|||||||
__ bind(&inner_push_loop);
|
__ bind(&inner_push_loop);
|
||||||
__ sub(r3, r3, Operand(sizeof(uint32_t)));
|
__ sub(r3, r3, Operand(sizeof(uint32_t)));
|
||||||
__ add(r6, r2, Operand(r3));
|
__ add(r6, r2, Operand(r3));
|
||||||
__ ldr(r7, MemOperand(r6, FrameDescription::frame_content_offset()));
|
__ ldr(r6, MemOperand(r6, FrameDescription::frame_content_offset()));
|
||||||
__ push(r7);
|
__ push(r6);
|
||||||
__ bind(&inner_loop_header);
|
__ bind(&inner_loop_header);
|
||||||
__ cmp(r3, Operand::Zero());
|
__ cmp(r3, Operand::Zero());
|
||||||
__ b(ne, &inner_push_loop); // test for gt?
|
__ b(ne, &inner_push_loop); // test for gt?
|
||||||
@ -315,9 +315,9 @@ void Deoptimizer::EntryGenerator::Generate() {
|
|||||||
__ InitializeRootRegister();
|
__ InitializeRootRegister();
|
||||||
|
|
||||||
__ pop(ip); // remove pc
|
__ pop(ip); // remove pc
|
||||||
__ pop(r7); // get continuation, leave pc on stack
|
__ pop(ip); // get continuation, leave pc on stack
|
||||||
__ pop(lr);
|
__ pop(lr);
|
||||||
__ Jump(r7);
|
__ Jump(ip);
|
||||||
__ stop("Unreachable.");
|
__ stop("Unreachable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ const RegList kCalleeSaved =
|
|||||||
1 << 4 | // r4 v1
|
1 << 4 | // r4 v1
|
||||||
1 << 5 | // r5 v2
|
1 << 5 | // r5 v2
|
||||||
1 << 6 | // r6 v3
|
1 << 6 | // r6 v3
|
||||||
1 << 7 | // r7 v4
|
1 << 7 | // r7 v4 (pp in JavaScript code)
|
||||||
1 << 8 | // r8 v5 (cp in JavaScript code)
|
1 << 8 | // r8 v5 (cp in JavaScript code)
|
||||||
kR9Available << 9 | // r9 v6
|
kR9Available << 9 | // r9 v6
|
||||||
1 << 10 | // r10 v7
|
1 << 10 | // r10 v7
|
||||||
|
@ -3962,9 +3962,8 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||||
Label bailout, done, one_char_separator, long_separator,
|
Label bailout, done, one_char_separator, long_separator, non_trivial_array,
|
||||||
non_trivial_array, not_size_one_array, loop,
|
not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
|
||||||
empty_separator_loop, one_char_separator_loop,
|
|
||||||
one_char_separator_loop_entry, long_separator_loop;
|
one_char_separator_loop_entry, long_separator_loop;
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
@ -3982,19 +3981,18 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
Register string = r4;
|
Register string = r4;
|
||||||
Register element = r5;
|
Register element = r5;
|
||||||
Register elements_end = r6;
|
Register elements_end = r6;
|
||||||
Register scratch1 = r7;
|
Register scratch = r9;
|
||||||
Register scratch2 = r9;
|
|
||||||
|
|
||||||
// Separator operand is on the stack.
|
// Separator operand is on the stack.
|
||||||
__ pop(separator);
|
__ pop(separator);
|
||||||
|
|
||||||
// Check that the array is a JSArray.
|
// Check that the array is a JSArray.
|
||||||
__ JumpIfSmi(array, &bailout);
|
__ JumpIfSmi(array, &bailout);
|
||||||
__ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
|
__ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
|
||||||
__ b(ne, &bailout);
|
__ b(ne, &bailout);
|
||||||
|
|
||||||
// Check that the array has fast elements.
|
// Check that the array has fast elements.
|
||||||
__ CheckFastElements(scratch1, scratch2, &bailout);
|
__ CheckFastElements(scratch, array_length, &bailout);
|
||||||
|
|
||||||
// If the array has length zero, return the empty string.
|
// If the array has length zero, return the empty string.
|
||||||
__ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
|
__ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
|
||||||
@ -4031,11 +4029,11 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
|
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
|
||||||
__ JumpIfSmi(string, &bailout);
|
__ JumpIfSmi(string, &bailout);
|
||||||
__ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
|
||||||
__ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
|
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
||||||
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
|
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
|
||||||
__ ldr(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
|
__ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
|
||||||
__ add(string_length, string_length, Operand(scratch1), SetCC);
|
__ add(string_length, string_length, Operand(scratch), SetCC);
|
||||||
__ b(vs, &bailout);
|
__ b(vs, &bailout);
|
||||||
__ cmp(element, elements_end);
|
__ cmp(element, elements_end);
|
||||||
__ b(lt, &loop);
|
__ b(lt, &loop);
|
||||||
@ -4056,23 +4054,23 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
|
|
||||||
// Check that the separator is a flat ASCII string.
|
// Check that the separator is a flat ASCII string.
|
||||||
__ JumpIfSmi(separator, &bailout);
|
__ JumpIfSmi(separator, &bailout);
|
||||||
__ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
|
__ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
|
||||||
__ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
|
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
||||||
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
|
__ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
|
||||||
|
|
||||||
// Add (separator length times array_length) - separator length to the
|
// Add (separator length times array_length) - separator length to the
|
||||||
// string_length to get the length of the result string. array_length is not
|
// string_length to get the length of the result string. array_length is not
|
||||||
// smi but the other values are, so the result is a smi
|
// smi but the other values are, so the result is a smi
|
||||||
__ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
|
__ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
|
||||||
__ sub(string_length, string_length, Operand(scratch1));
|
__ sub(string_length, string_length, Operand(scratch));
|
||||||
__ smull(scratch2, ip, array_length, scratch1);
|
__ smull(scratch, ip, array_length, scratch);
|
||||||
// Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
|
// Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
|
||||||
// zero.
|
// zero.
|
||||||
__ cmp(ip, Operand::Zero());
|
__ cmp(ip, Operand::Zero());
|
||||||
__ b(ne, &bailout);
|
__ b(ne, &bailout);
|
||||||
__ tst(scratch2, Operand(0x80000000));
|
__ tst(scratch, Operand(0x80000000));
|
||||||
__ b(ne, &bailout);
|
__ b(ne, &bailout);
|
||||||
__ add(string_length, string_length, Operand(scratch2), SetCC);
|
__ add(string_length, string_length, Operand(scratch), SetCC);
|
||||||
__ b(vs, &bailout);
|
__ b(vs, &bailout);
|
||||||
__ SmiUntag(string_length);
|
__ SmiUntag(string_length);
|
||||||
|
|
||||||
@ -4089,9 +4087,9 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
// array_length: Length of the array.
|
// array_length: Length of the array.
|
||||||
__ AllocateAsciiString(result,
|
__ AllocateAsciiString(result,
|
||||||
string_length,
|
string_length,
|
||||||
scratch1,
|
scratch,
|
||||||
scratch2,
|
string, // used as scratch
|
||||||
elements_end,
|
elements_end, // used as scratch
|
||||||
&bailout);
|
&bailout);
|
||||||
// Prepare for looping. Set up elements_end to end of the array. Set
|
// Prepare for looping. Set up elements_end to end of the array. Set
|
||||||
// result_pos to the position of the result where to write the first
|
// result_pos to the position of the result where to write the first
|
||||||
@ -4104,8 +4102,8 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
|
|
||||||
// Check the length of the separator.
|
// Check the length of the separator.
|
||||||
__ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
|
__ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
|
||||||
__ cmp(scratch1, Operand(Smi::FromInt(1)));
|
__ cmp(scratch, Operand(Smi::FromInt(1)));
|
||||||
__ b(eq, &one_char_separator);
|
__ b(eq, &one_char_separator);
|
||||||
__ b(gt, &long_separator);
|
__ b(gt, &long_separator);
|
||||||
|
|
||||||
@ -4123,7 +4121,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
__ add(string,
|
__ add(string,
|
||||||
string,
|
string,
|
||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ CopyBytes(string, result_pos, string_length, scratch1);
|
__ CopyBytes(string, result_pos, string_length, scratch);
|
||||||
__ cmp(element, elements_end);
|
__ cmp(element, elements_end);
|
||||||
__ b(lt, &empty_separator_loop); // End while (element < elements_end).
|
__ b(lt, &empty_separator_loop); // End while (element < elements_end).
|
||||||
ASSERT(result.is(r0));
|
ASSERT(result.is(r0));
|
||||||
@ -4155,7 +4153,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
__ add(string,
|
__ add(string,
|
||||||
string,
|
string,
|
||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ CopyBytes(string, result_pos, string_length, scratch1);
|
__ CopyBytes(string, result_pos, string_length, scratch);
|
||||||
__ cmp(element, elements_end);
|
__ cmp(element, elements_end);
|
||||||
__ b(lt, &one_char_separator_loop); // End while (element < elements_end).
|
__ b(lt, &one_char_separator_loop); // End while (element < elements_end).
|
||||||
ASSERT(result.is(r0));
|
ASSERT(result.is(r0));
|
||||||
@ -4176,7 +4174,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
__ add(string,
|
__ add(string,
|
||||||
separator,
|
separator,
|
||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ CopyBytes(string, result_pos, string_length, scratch1);
|
__ CopyBytes(string, result_pos, string_length, scratch);
|
||||||
|
|
||||||
__ bind(&long_separator);
|
__ bind(&long_separator);
|
||||||
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
|
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
|
||||||
@ -4185,7 +4183,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
|||||||
__ add(string,
|
__ add(string,
|
||||||
string,
|
string,
|
||||||
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ CopyBytes(string, result_pos, string_length, scratch1);
|
__ CopyBytes(string, result_pos, string_length, scratch);
|
||||||
__ cmp(element, elements_end);
|
__ cmp(element, elements_end);
|
||||||
__ b(lt, &long_separator_loop); // End while (element < elements_end).
|
__ b(lt, &long_separator_loop); // End while (element < elements_end).
|
||||||
ASSERT(result.is(r0));
|
ASSERT(result.is(r0));
|
||||||
|
@ -1394,7 +1394,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
Register receiver = r2;
|
Register receiver = r2;
|
||||||
Register receiver_map = r3;
|
Register receiver_map = r3;
|
||||||
Register elements_map = r6;
|
Register elements_map = r6;
|
||||||
Register elements = r7; // Elements array of the receiver.
|
Register elements = r9; // Elements array of the receiver.
|
||||||
// r4 and r5 are used as general scratch registers.
|
// r4 and r5 are used as general scratch registers.
|
||||||
|
|
||||||
// Check that the key is a smi.
|
// Check that the key is a smi.
|
||||||
|
@ -3879,9 +3879,9 @@ void LCodeGen::DoPower(LPower* instr) {
|
|||||||
} else if (exponent_type.IsTagged()) {
|
} else if (exponent_type.IsTagged()) {
|
||||||
Label no_deopt;
|
Label no_deopt;
|
||||||
__ JumpIfSmi(r2, &no_deopt);
|
__ JumpIfSmi(r2, &no_deopt);
|
||||||
__ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset));
|
__ ldr(r6, FieldMemOperand(r2, HeapObject::kMapOffset));
|
||||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||||
__ cmp(r7, Operand(ip));
|
__ cmp(r6, Operand(ip));
|
||||||
DeoptimizeIf(ne, instr->environment());
|
DeoptimizeIf(ne, instr->environment());
|
||||||
__ bind(&no_deopt);
|
__ bind(&no_deopt);
|
||||||
MathPowStub stub(MathPowStub::TAGGED);
|
MathPowStub stub(MathPowStub::TAGGED);
|
||||||
@ -5386,24 +5386,24 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
|
|||||||
void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
||||||
Label materialized;
|
Label materialized;
|
||||||
// Registers will be used as follows:
|
// Registers will be used as follows:
|
||||||
// r7 = literals array.
|
// r6 = literals array.
|
||||||
// r1 = regexp literal.
|
// r1 = regexp literal.
|
||||||
// r0 = regexp literal clone.
|
// r0 = regexp literal clone.
|
||||||
// r2 and r4-r6 are used as temporaries.
|
// r2-5 are used as temporaries.
|
||||||
int literal_offset =
|
int literal_offset =
|
||||||
FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
|
FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
|
||||||
__ LoadHeapObject(r7, instr->hydrogen()->literals());
|
__ LoadHeapObject(r6, instr->hydrogen()->literals());
|
||||||
__ ldr(r1, FieldMemOperand(r7, literal_offset));
|
__ ldr(r1, FieldMemOperand(r6, literal_offset));
|
||||||
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
||||||
__ cmp(r1, ip);
|
__ cmp(r1, ip);
|
||||||
__ b(ne, &materialized);
|
__ b(ne, &materialized);
|
||||||
|
|
||||||
// Create regexp literal using runtime function
|
// Create regexp literal using runtime function
|
||||||
// Result will be in r0.
|
// Result will be in r0.
|
||||||
__ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
|
__ mov(r5, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
|
||||||
__ mov(r5, Operand(instr->hydrogen()->pattern()));
|
__ mov(r4, Operand(instr->hydrogen()->pattern()));
|
||||||
__ mov(r4, Operand(instr->hydrogen()->flags()));
|
__ mov(r3, Operand(instr->hydrogen()->flags()));
|
||||||
__ Push(r7, r6, r5, r4);
|
__ Push(r6, r5, r4, r3);
|
||||||
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
|
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
|
||||||
__ mov(r1, r0);
|
__ mov(r1, r0);
|
||||||
|
|
||||||
|
@ -1337,7 +1337,7 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
|||||||
STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
|
STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
|
||||||
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
|
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
|
||||||
|
|
||||||
// For the JSEntry handler, we must preserve r0-r4, r5-r7 are available.
|
// For the JSEntry handler, we must preserve r0-r4, r5-r6 are available.
|
||||||
// We will build up the handler from the bottom by pushing on the stack.
|
// We will build up the handler from the bottom by pushing on the stack.
|
||||||
// Set up the code object (r5) and the state (r6) for pushing.
|
// Set up the code object (r5) and the state (r6) for pushing.
|
||||||
unsigned state =
|
unsigned state =
|
||||||
@ -1348,9 +1348,9 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
|
|||||||
|
|
||||||
// Push the frame pointer, context, state, and code object.
|
// Push the frame pointer, context, state, and code object.
|
||||||
if (kind == StackHandler::JS_ENTRY) {
|
if (kind == StackHandler::JS_ENTRY) {
|
||||||
mov(r7, Operand(Smi::FromInt(0))); // Indicates no context.
|
mov(cp, Operand(Smi::FromInt(0))); // Indicates no context.
|
||||||
mov(ip, Operand::Zero()); // NULL frame pointer.
|
mov(ip, Operand::Zero()); // NULL frame pointer.
|
||||||
stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit());
|
stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | ip.bit());
|
||||||
} else {
|
} else {
|
||||||
stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
|
stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
|
||||||
}
|
}
|
||||||
@ -2305,13 +2305,15 @@ void MacroAssembler::CallApiFunctionAndReturn(
|
|||||||
ExternalReference::handle_scope_level_address(isolate()),
|
ExternalReference::handle_scope_level_address(isolate()),
|
||||||
next_address);
|
next_address);
|
||||||
|
|
||||||
|
ASSERT(!thunk_last_arg.is(r3));
|
||||||
|
|
||||||
// Allocate HandleScope in callee-save registers.
|
// Allocate HandleScope in callee-save registers.
|
||||||
mov(r7, Operand(next_address));
|
mov(r9, Operand(next_address));
|
||||||
ldr(r4, MemOperand(r7, kNextOffset));
|
ldr(r4, MemOperand(r9, kNextOffset));
|
||||||
ldr(r5, MemOperand(r7, kLimitOffset));
|
ldr(r5, MemOperand(r9, kLimitOffset));
|
||||||
ldr(r6, MemOperand(r7, kLevelOffset));
|
ldr(r6, MemOperand(r9, kLevelOffset));
|
||||||
add(r6, r6, Operand(1));
|
add(r6, r6, Operand(1));
|
||||||
str(r6, MemOperand(r7, kLevelOffset));
|
str(r6, MemOperand(r9, kLevelOffset));
|
||||||
|
|
||||||
if (FLAG_log_timer_events) {
|
if (FLAG_log_timer_events) {
|
||||||
FrameScope frame(this, StackFrame::MANUAL);
|
FrameScope frame(this, StackFrame::MANUAL);
|
||||||
@ -2322,7 +2324,6 @@ void MacroAssembler::CallApiFunctionAndReturn(
|
|||||||
PopSafepointRegisters();
|
PopSafepointRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(!thunk_last_arg.is(r3));
|
|
||||||
Label profiler_disabled;
|
Label profiler_disabled;
|
||||||
Label end_profiler_check;
|
Label end_profiler_check;
|
||||||
bool* is_profiling_flag =
|
bool* is_profiling_flag =
|
||||||
@ -2368,15 +2369,15 @@ void MacroAssembler::CallApiFunctionAndReturn(
|
|||||||
bind(&return_value_loaded);
|
bind(&return_value_loaded);
|
||||||
// No more valid handles (the result handle was the last one). Restore
|
// No more valid handles (the result handle was the last one). Restore
|
||||||
// previous handle scope.
|
// previous handle scope.
|
||||||
str(r4, MemOperand(r7, kNextOffset));
|
str(r4, MemOperand(r9, kNextOffset));
|
||||||
if (emit_debug_code()) {
|
if (emit_debug_code()) {
|
||||||
ldr(r1, MemOperand(r7, kLevelOffset));
|
ldr(r1, MemOperand(r9, kLevelOffset));
|
||||||
cmp(r1, r6);
|
cmp(r1, r6);
|
||||||
Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
|
Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
|
||||||
}
|
}
|
||||||
sub(r6, r6, Operand(1));
|
sub(r6, r6, Operand(1));
|
||||||
str(r6, MemOperand(r7, kLevelOffset));
|
str(r6, MemOperand(r9, kLevelOffset));
|
||||||
ldr(ip, MemOperand(r7, kLimitOffset));
|
ldr(ip, MemOperand(r9, kLimitOffset));
|
||||||
cmp(r5, ip);
|
cmp(r5, ip);
|
||||||
b(ne, &delete_allocated_handles);
|
b(ne, &delete_allocated_handles);
|
||||||
|
|
||||||
@ -2409,7 +2410,7 @@ void MacroAssembler::CallApiFunctionAndReturn(
|
|||||||
|
|
||||||
// HandleScope limit has changed. Delete allocated extensions.
|
// HandleScope limit has changed. Delete allocated extensions.
|
||||||
bind(&delete_allocated_handles);
|
bind(&delete_allocated_handles);
|
||||||
str(r5, MemOperand(r7, kLimitOffset));
|
str(r5, MemOperand(r9, kLimitOffset));
|
||||||
mov(r4, r0);
|
mov(r4, r0);
|
||||||
PrepareCallCFunction(1, r5);
|
PrepareCallCFunction(1, r5);
|
||||||
mov(r0, Operand(ExternalReference::isolate_address(isolate())));
|
mov(r0, Operand(ExternalReference::isolate_address(isolate())));
|
||||||
|
@ -45,8 +45,9 @@ inline MemOperand FieldMemOperand(Register object, int offset) {
|
|||||||
|
|
||||||
|
|
||||||
// Give alias names to registers
|
// Give alias names to registers
|
||||||
const Register cp = { 8 }; // JavaScript context pointer
|
const Register pp = { kRegister_r7_Code }; // Constant pool pointer.
|
||||||
const Register kRootRegister = { 10 }; // Roots array pointer.
|
const Register cp = { kRegister_r8_Code }; // JavaScript context pointer.
|
||||||
|
const Register kRootRegister = { kRegister_r10_Code }; // Roots array pointer.
|
||||||
|
|
||||||
// Flags used for AllocateHeapNumber
|
// Flags used for AllocateHeapNumber
|
||||||
enum TaggingMode {
|
enum TaggingMode {
|
||||||
|
@ -874,8 +874,8 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
|||||||
// Store call data.
|
// Store call data.
|
||||||
__ str(r6, MemOperand(sp, 3 * kPointerSize));
|
__ str(r6, MemOperand(sp, 3 * kPointerSize));
|
||||||
// Store isolate.
|
// Store isolate.
|
||||||
__ mov(r7, Operand(ExternalReference::isolate_address(masm->isolate())));
|
__ mov(r5, Operand(ExternalReference::isolate_address(masm->isolate())));
|
||||||
__ str(r7, MemOperand(sp, 4 * kPointerSize));
|
__ str(r5, MemOperand(sp, 4 * kPointerSize));
|
||||||
// Store ReturnValue default and ReturnValue.
|
// Store ReturnValue default and ReturnValue.
|
||||||
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
|
||||||
__ str(r5, MemOperand(sp, 5 * kPointerSize));
|
__ str(r5, MemOperand(sp, 5 * kPointerSize));
|
||||||
@ -1855,15 +1855,15 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
|
|
||||||
if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
|
if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
|
||||||
Label fast_object, not_fast_object;
|
Label fast_object, not_fast_object;
|
||||||
__ CheckFastObjectElements(r3, r7, ¬_fast_object);
|
__ CheckFastObjectElements(r3, r9, ¬_fast_object);
|
||||||
__ jmp(&fast_object);
|
__ jmp(&fast_object);
|
||||||
// In case of fast smi-only, convert to fast object, otherwise bail out.
|
// In case of fast smi-only, convert to fast object, otherwise bail out.
|
||||||
__ bind(¬_fast_object);
|
__ bind(¬_fast_object);
|
||||||
__ CheckFastSmiElements(r3, r7, &call_builtin);
|
__ CheckFastSmiElements(r3, r9, &call_builtin);
|
||||||
|
|
||||||
__ ldr(r7, FieldMemOperand(r4, HeapObject::kMapOffset));
|
__ ldr(r9, FieldMemOperand(r4, HeapObject::kMapOffset));
|
||||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||||
__ cmp(r7, ip);
|
__ cmp(r9, ip);
|
||||||
__ b(eq, &call_builtin);
|
__ b(eq, &call_builtin);
|
||||||
// edx: receiver
|
// edx: receiver
|
||||||
// r3: map
|
// r3: map
|
||||||
@ -1871,7 +1871,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
__ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
__ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
||||||
FAST_ELEMENTS,
|
FAST_ELEMENTS,
|
||||||
r3,
|
r3,
|
||||||
r7,
|
r9,
|
||||||
&try_holey_map);
|
&try_holey_map);
|
||||||
__ mov(r2, receiver);
|
__ mov(r2, receiver);
|
||||||
ElementsTransitionGenerator::
|
ElementsTransitionGenerator::
|
||||||
@ -1884,7 +1884,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
__ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
|
__ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
|
||||||
FAST_HOLEY_ELEMENTS,
|
FAST_HOLEY_ELEMENTS,
|
||||||
r3,
|
r3,
|
||||||
r7,
|
r9,
|
||||||
&call_builtin);
|
&call_builtin);
|
||||||
__ mov(r2, receiver);
|
__ mov(r2, receiver);
|
||||||
ElementsTransitionGenerator::
|
ElementsTransitionGenerator::
|
||||||
@ -1917,7 +1917,6 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
|
|
||||||
__ bind(&attempt_to_grow_elements);
|
__ bind(&attempt_to_grow_elements);
|
||||||
// r0: array's length + 1.
|
// r0: array's length + 1.
|
||||||
// r4: elements' length.
|
|
||||||
|
|
||||||
if (!FLAG_inline_new) {
|
if (!FLAG_inline_new) {
|
||||||
__ b(&call_builtin);
|
__ b(&call_builtin);
|
||||||
@ -1928,8 +1927,8 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
// the new element is non-Smi. For now, delegate to the builtin.
|
// the new element is non-Smi. For now, delegate to the builtin.
|
||||||
Label no_fast_elements_check;
|
Label no_fast_elements_check;
|
||||||
__ JumpIfSmi(r2, &no_fast_elements_check);
|
__ JumpIfSmi(r2, &no_fast_elements_check);
|
||||||
__ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
__ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||||
__ CheckFastObjectElements(r7, r7, &call_builtin);
|
__ CheckFastObjectElements(r9, r9, &call_builtin);
|
||||||
__ bind(&no_fast_elements_check);
|
__ bind(&no_fast_elements_check);
|
||||||
|
|
||||||
ExternalReference new_space_allocation_top =
|
ExternalReference new_space_allocation_top =
|
||||||
@ -1941,8 +1940,8 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
// Load top and check if it is the end of elements.
|
// Load top and check if it is the end of elements.
|
||||||
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
|
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
|
||||||
__ add(end_elements, end_elements, Operand(kEndElementsOffset));
|
__ add(end_elements, end_elements, Operand(kEndElementsOffset));
|
||||||
__ mov(r7, Operand(new_space_allocation_top));
|
__ mov(r4, Operand(new_space_allocation_top));
|
||||||
__ ldr(r3, MemOperand(r7));
|
__ ldr(r3, MemOperand(r4));
|
||||||
__ cmp(end_elements, r3);
|
__ cmp(end_elements, r3);
|
||||||
__ b(ne, &call_builtin);
|
__ b(ne, &call_builtin);
|
||||||
|
|
||||||
@ -1954,7 +1953,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
|
|
||||||
// We fit and could grow elements.
|
// We fit and could grow elements.
|
||||||
// Update new_space_allocation_top.
|
// Update new_space_allocation_top.
|
||||||
__ str(r3, MemOperand(r7));
|
__ str(r3, MemOperand(r4));
|
||||||
// Push the argument.
|
// Push the argument.
|
||||||
__ str(r2, MemOperand(end_elements));
|
__ str(r2, MemOperand(end_elements));
|
||||||
// Fill the rest with holes.
|
// Fill the rest with holes.
|
||||||
@ -1965,6 +1964,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
|||||||
|
|
||||||
// Update elements' and array's sizes.
|
// Update elements' and array's sizes.
|
||||||
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
||||||
|
__ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
||||||
__ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
|
__ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
|
||||||
__ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
__ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
||||||
|
|
||||||
|
@ -826,6 +826,16 @@ DEFINE_implication(print_all_code, trace_codegen)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read-only flags
|
||||||
|
//
|
||||||
|
#undef FLAG
|
||||||
|
#define FLAG FLAG_READONLY
|
||||||
|
|
||||||
|
// assembler-arm.h
|
||||||
|
DEFINE_bool(enable_ool_constant_pool, false,
|
||||||
|
"enable use of out-of-line constant pools (ARM only)")
|
||||||
|
|
||||||
// Cleanup...
|
// Cleanup...
|
||||||
#undef FLAG_FULL
|
#undef FLAG_FULL
|
||||||
#undef FLAG_READONLY
|
#undef FLAG_READONLY
|
||||||
|
Loading…
Reference in New Issue
Block a user