| Index: src/ia32/code-stubs-ia32.cc
|
| ===================================================================
|
| --- src/ia32/code-stubs-ia32.cc (revision 7948)
|
| +++ src/ia32/code-stubs-ia32.cc (working copy)
|
| @@ -29,8 +29,8 @@
|
|
|
| #if defined(V8_TARGET_ARCH_IA32)
|
|
|
| +#include "bootstrapper.h"
|
| #include "code-stubs.h"
|
| -#include "bootstrapper.h"
|
| #include "isolate.h"
|
| #include "jsregexp.h"
|
| #include "macro-assembler-ia32-inl.h"
|
| @@ -43,16 +43,16 @@
|
|
|
| void ToNumberStub::Generate(MacroAssembler* masm) {
|
| // The ToNumber stub takes one argument in eax.
|
| - NearLabel check_heap_number, call_builtin;
|
| + Label check_heap_number, call_builtin;
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &check_heap_number);
|
| + __ j(not_zero, &check_heap_number, Label::kNear);
|
| __ ret(0);
|
|
|
| __ bind(&check_heap_number);
|
| __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
| Factory* factory = masm->isolate()->factory();
|
| __ cmp(Operand(ebx), Immediate(factory->heap_number_map()));
|
| - __ j(not_equal, &call_builtin);
|
| + __ j(not_equal, &call_builtin, Label::kNear);
|
| __ ret(0);
|
|
|
| __ bind(&call_builtin);
|
| @@ -243,13 +243,29 @@
|
|
|
| // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
|
| void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| - NearLabel false_result, true_result, not_string;
|
| + Label false_result, true_result, not_string;
|
| __ mov(eax, Operand(esp, 1 * kPointerSize));
|
| + Factory* factory = masm->isolate()->factory();
|
|
|
| + // undefined -> false
|
| + __ cmp(eax, factory->undefined_value());
|
| + __ j(equal, &false_result);
|
| +
|
| + // Boolean -> its value
|
| + __ cmp(eax, factory->true_value());
|
| + __ j(equal, &true_result);
|
| + __ cmp(eax, factory->false_value());
|
| + __ j(equal, &false_result);
|
| +
|
| + // Smis: 0 -> false, all other -> true
|
| + __ test(eax, Operand(eax));
|
| + __ j(zero, &false_result);
|
| + __ test(eax, Immediate(kSmiTagMask));
|
| + __ j(zero, &true_result);
|
| +
|
| // 'null' => false.
|
| - Factory* factory = masm->isolate()->factory();
|
| __ cmp(eax, factory->null_value());
|
| - __ j(equal, &false_result);
|
| + __ j(equal, &false_result, Label::kNear);
|
|
|
| // Get the map and type of the heap object.
|
| __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
| @@ -258,28 +274,28 @@
|
| // Undetectable => false.
|
| __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
|
| 1 << Map::kIsUndetectable);
|
| - __ j(not_zero, &false_result);
|
| + __ j(not_zero, &false_result, Label::kNear);
|
|
|
| // JavaScript object => true.
|
| __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE);
|
| - __ j(above_equal, &true_result);
|
| + __ j(above_equal, &true_result, Label::kNear);
|
|
|
| // String value => false iff empty.
|
| __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
|
| - __ j(above_equal, ¬_string);
|
| + __ j(above_equal, ¬_string, Label::kNear);
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
|
| - __ j(zero, &false_result);
|
| - __ jmp(&true_result);
|
| + __ j(zero, &false_result, Label::kNear);
|
| + __ jmp(&true_result, Label::kNear);
|
|
|
| __ bind(¬_string);
|
| // HeapNumber => false iff +0, -0, or NaN.
|
| __ cmp(edx, factory->heap_number_map());
|
| - __ j(not_equal, &true_result);
|
| + __ j(not_equal, &true_result, Label::kNear);
|
| __ fldz();
|
| __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| __ FCmp();
|
| - __ j(zero, &false_result);
|
| + __ j(zero, &false_result, Label::kNear);
|
| // Fall through to |true_result|.
|
|
|
| // Return 1/0 for true/false in eax.
|
| @@ -365,14 +381,6 @@
|
|
|
| // Takes the operands in edx and eax and loads them as integers in eax
|
| // and ecx.
|
| - static void LoadAsIntegers(MacroAssembler* masm,
|
| - TypeInfo type_info,
|
| - bool use_sse3,
|
| - Label* operand_conversion_failure);
|
| - static void LoadNumbersAsIntegers(MacroAssembler* masm,
|
| - TypeInfo type_info,
|
| - bool use_sse3,
|
| - Label* operand_conversion_failure);
|
| static void LoadUnknownsAsIntegers(MacroAssembler* masm,
|
| bool use_sse3,
|
| Label* operand_conversion_failure);
|
| @@ -414,34 +422,24 @@
|
| // trashed registers.
|
| static void IntegerConvert(MacroAssembler* masm,
|
| Register source,
|
| - TypeInfo type_info,
|
| bool use_sse3,
|
| Label* conversion_failure) {
|
| ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx));
|
| Label done, right_exponent, normal_exponent;
|
| Register scratch = ebx;
|
| Register scratch2 = edi;
|
| - if (type_info.IsInteger32() && CpuFeatures::IsSupported(SSE2)) {
|
| - CpuFeatures::Scope scope(SSE2);
|
| - __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset));
|
| - return;
|
| - }
|
| - if (!type_info.IsInteger32() || !use_sse3) {
|
| - // Get exponent word.
|
| - __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
|
| - // Get exponent alone in scratch2.
|
| - __ mov(scratch2, scratch);
|
| - __ and_(scratch2, HeapNumber::kExponentMask);
|
| - }
|
| + // Get exponent word.
|
| + __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
|
| + // Get exponent alone in scratch2.
|
| + __ mov(scratch2, scratch);
|
| + __ and_(scratch2, HeapNumber::kExponentMask);
|
| if (use_sse3) {
|
| CpuFeatures::Scope scope(SSE3);
|
| - if (!type_info.IsInteger32()) {
|
| - // Check whether the exponent is too big for a 64 bit signed integer.
|
| - static const uint32_t kTooBigExponent =
|
| - (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
|
| - __ cmp(Operand(scratch2), Immediate(kTooBigExponent));
|
| - __ j(greater_equal, conversion_failure);
|
| - }
|
| + // Check whether the exponent is too big for a 64 bit signed integer.
|
| + static const uint32_t kTooBigExponent =
|
| + (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
|
| + __ cmp(Operand(scratch2), Immediate(kTooBigExponent));
|
| + __ j(greater_equal, conversion_failure);
|
| // Load x87 register with heap number.
|
| __ fld_d(FieldOperand(source, HeapNumber::kValueOffset));
|
| // Reserve space for 64 bit answer.
|
| @@ -540,12 +538,12 @@
|
| __ shr_cl(scratch2);
|
| // Now the unsigned answer is in scratch2. We need to move it to ecx and
|
| // we may need to fix the sign.
|
| - NearLabel negative;
|
| + Label negative;
|
| __ xor_(ecx, Operand(ecx));
|
| __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset));
|
| - __ j(greater, &negative);
|
| + __ j(greater, &negative, Label::kNear);
|
| __ mov(ecx, scratch2);
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
| __ bind(&negative);
|
| __ sub(ecx, Operand(scratch2));
|
| __ bind(&done);
|
| @@ -639,9 +637,9 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| - Label undo, slow;
|
| - GenerateSmiCodeSub(masm, &non_smi, &undo, &slow);
|
| + Label non_smi, undo, slow;
|
| + GenerateSmiCodeSub(masm, &non_smi, &undo, &slow,
|
| + Label::kNear, Label::kNear, Label::kNear);
|
| __ bind(&undo);
|
| GenerateSmiCodeUndo(masm);
|
| __ bind(&non_smi);
|
| @@ -651,7 +649,7 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| + Label non_smi;
|
| GenerateSmiCodeBitNot(masm, &non_smi);
|
| __ bind(&non_smi);
|
| GenerateTypeTransition(masm);
|
| @@ -659,31 +657,36 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
| - NearLabel* non_smi,
|
| + Label* non_smi,
|
| Label* undo,
|
| - Label* slow) {
|
| + Label* slow,
|
| + Label::Distance non_smi_near,
|
| + Label::Distance undo_near,
|
| + Label::Distance slow_near) {
|
| // Check whether the value is a smi.
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, non_smi);
|
| + __ j(not_zero, non_smi, non_smi_near);
|
|
|
| // We can't handle -0 with smis, so use a type transition for that case.
|
| __ test(eax, Operand(eax));
|
| - __ j(zero, slow);
|
| + __ j(zero, slow, slow_near);
|
|
|
| // Try optimistic subtraction '0 - value', saving operand in eax for undo.
|
| __ mov(edx, Operand(eax));
|
| __ Set(eax, Immediate(0));
|
| __ sub(eax, Operand(edx));
|
| - __ j(overflow, undo);
|
| + __ j(overflow, undo, undo_near);
|
| __ ret(0);
|
| }
|
|
|
|
|
| -void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
| - NearLabel* non_smi) {
|
| +void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
|
| + MacroAssembler* masm,
|
| + Label* non_smi,
|
| + Label::Distance non_smi_near) {
|
| // Check whether the value is a smi.
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, non_smi);
|
| + __ j(not_zero, non_smi, non_smi_near);
|
|
|
| // Flip bits and revert inverted smi-tag.
|
| __ not_(eax);
|
| @@ -713,23 +716,23 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| - Label undo, slow;
|
| - GenerateSmiCodeSub(masm, &non_smi, &undo, &slow);
|
| + Label non_smi, undo, slow, call_builtin;
|
| + GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
|
| __ bind(&non_smi);
|
| GenerateHeapNumberCodeSub(masm, &slow);
|
| __ bind(&undo);
|
| GenerateSmiCodeUndo(masm);
|
| __ bind(&slow);
|
| GenerateTypeTransition(masm);
|
| + __ bind(&call_builtin);
|
| + GenerateGenericCodeFallback(masm);
|
| }
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
| MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| - Label slow;
|
| - GenerateSmiCodeBitNot(masm, &non_smi);
|
| + Label non_smi, slow;
|
| + GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
| __ bind(&non_smi);
|
| GenerateHeapNumberCodeBitNot(masm, &slow);
|
| __ bind(&slow);
|
| @@ -781,14 +784,13 @@
|
| __ j(not_equal, slow);
|
|
|
| // Convert the heap number in eax to an untagged integer in ecx.
|
| - IntegerConvert(masm, eax, TypeInfo::Unknown(), CpuFeatures::IsSupported(SSE3),
|
| - slow);
|
| + IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow);
|
|
|
| // Do the bitwise operation and check if the result fits in a smi.
|
| - NearLabel try_float;
|
| + Label try_float;
|
| __ not_(ecx);
|
| __ cmp(ecx, 0xc0000000);
|
| - __ j(sign, &try_float);
|
| + __ j(sign, &try_float, Label::kNear);
|
|
|
| // Tag the result as a smi and we're done.
|
| STATIC_ASSERT(kSmiTagSize == 1);
|
| @@ -815,8 +817,7 @@
|
| __ LeaveInternalFrame();
|
| // IntegerConvert uses ebx and edi as scratch registers.
|
| // This conversion won't go slow-case.
|
| - IntegerConvert(masm, edx, TypeInfo::Unknown(),
|
| - CpuFeatures::IsSupported(SSE3), slow);
|
| + IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow);
|
| __ not_(ecx);
|
|
|
| __ bind(&heapnumber_allocated);
|
| @@ -851,9 +852,8 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| - Label undo, slow;
|
| - GenerateSmiCodeSub(masm, &non_smi, &undo, &slow);
|
| + Label non_smi, undo, slow;
|
| + GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear);
|
| __ bind(&non_smi);
|
| GenerateHeapNumberCodeSub(masm, &slow);
|
| __ bind(&undo);
|
| @@ -864,9 +864,8 @@
|
|
|
|
|
| void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
| - NearLabel non_smi;
|
| - Label slow;
|
| - GenerateSmiCodeBitNot(masm, &non_smi);
|
| + Label non_smi, slow;
|
| + GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
| __ bind(&non_smi);
|
| GenerateHeapNumberCodeBitNot(masm, &slow);
|
| __ bind(&slow);
|
| @@ -1064,7 +1063,7 @@
|
| // 3. Perform the smi check of the operands.
|
| STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case.
|
| __ test(combined, Immediate(kSmiTagMask));
|
| - __ j(not_zero, ¬_smis, not_taken);
|
| + __ j(not_zero, ¬_smis);
|
|
|
| // 4. Operands are both smis, perform the operation leaving the result in
|
| // eax and check the result if necessary.
|
| @@ -1093,7 +1092,7 @@
|
| __ shl_cl(left);
|
| // Check that the *signed* result fits in a smi.
|
| __ cmp(left, 0xc0000000);
|
| - __ j(sign, &use_fp_on_smis, not_taken);
|
| + __ j(sign, &use_fp_on_smis);
|
| // Tag the result and store it in register eax.
|
| __ SmiTag(left);
|
| __ mov(eax, left);
|
| @@ -1123,7 +1122,7 @@
|
| // Smi tagging these two cases can only happen with shifts
|
| // by 0 or 1 when handed a valid smi.
|
| __ test(left, Immediate(0xc0000000));
|
| - __ j(not_zero, slow, not_taken);
|
| + __ j(not_zero, &use_fp_on_smis);
|
| // Tag the result and store it in register eax.
|
| __ SmiTag(left);
|
| __ mov(eax, left);
|
| @@ -1132,12 +1131,12 @@
|
| case Token::ADD:
|
| ASSERT(right.is(eax));
|
| __ add(right, Operand(left)); // Addition is commutative.
|
| - __ j(overflow, &use_fp_on_smis, not_taken);
|
| + __ j(overflow, &use_fp_on_smis);
|
| break;
|
|
|
| case Token::SUB:
|
| __ sub(left, Operand(right));
|
| - __ j(overflow, &use_fp_on_smis, not_taken);
|
| + __ j(overflow, &use_fp_on_smis);
|
| __ mov(eax, left);
|
| break;
|
|
|
| @@ -1151,7 +1150,7 @@
|
| __ SmiUntag(right);
|
| // Do multiplication.
|
| __ imul(right, Operand(left)); // Multiplication is commutative.
|
| - __ j(overflow, &use_fp_on_smis, not_taken);
|
| + __ j(overflow, &use_fp_on_smis);
|
| // Check for negative zero result. Use combined = left | right.
|
| __ NegativeZeroTest(right, combined, &use_fp_on_smis);
|
| break;
|
| @@ -1162,7 +1161,7 @@
|
| __ mov(edi, left);
|
| // Check for 0 divisor.
|
| __ test(right, Operand(right));
|
| - __ j(zero, &use_fp_on_smis, not_taken);
|
| + __ j(zero, &use_fp_on_smis);
|
| // Sign extend left into edx:eax.
|
| ASSERT(left.is(eax));
|
| __ cdq();
|
| @@ -1186,7 +1185,7 @@
|
| case Token::MOD:
|
| // Check for 0 divisor.
|
| __ test(right, Operand(right));
|
| - __ j(zero, ¬_smis, not_taken);
|
| + __ j(zero, ¬_smis);
|
|
|
| // Sign extend left into edx:eax.
|
| ASSERT(left.is(eax));
|
| @@ -1259,26 +1258,35 @@
|
| } else {
|
| ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS);
|
| switch (op_) {
|
| - case Token::SHL: {
|
| + case Token::SHL:
|
| + case Token::SHR: {
|
| Comment perform_float(masm, "-- Perform float operation on smis");
|
| __ bind(&use_fp_on_smis);
|
| // Result we want is in left == edx, so we can put the allocated heap
|
| // number in eax.
|
| __ AllocateHeapNumber(eax, ecx, ebx, slow);
|
| // Store the result in the HeapNumber and return.
|
| - if (CpuFeatures::IsSupported(SSE2)) {
|
| - CpuFeatures::Scope use_sse2(SSE2);
|
| - __ cvtsi2sd(xmm0, Operand(left));
|
| - __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
| - } else {
|
| - // It's OK to overwrite the right argument on the stack because we
|
| - // are about to return.
|
| + // It's OK to overwrite the arguments on the stack because we
|
| + // are about to return.
|
| + if (op_ == Token::SHR) {
|
| __ mov(Operand(esp, 1 * kPointerSize), left);
|
| - __ fild_s(Operand(esp, 1 * kPointerSize));
|
| + __ mov(Operand(esp, 2 * kPointerSize), Immediate(0));
|
| + __ fild_d(Operand(esp, 1 * kPointerSize));
|
| __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| + } else {
|
| + ASSERT_EQ(Token::SHL, op_);
|
| + if (CpuFeatures::IsSupported(SSE2)) {
|
| + CpuFeatures::Scope use_sse2(SSE2);
|
| + __ cvtsi2sd(xmm0, Operand(left));
|
| + __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
| + } else {
|
| + __ mov(Operand(esp, 1 * kPointerSize), left);
|
| + __ fild_s(Operand(esp, 1 * kPointerSize));
|
| + __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| + }
|
| }
|
| - __ ret(2 * kPointerSize);
|
| - break;
|
| + __ ret(2 * kPointerSize);
|
| + break;
|
| }
|
|
|
| case Token::ADD:
|
| @@ -1578,7 +1586,7 @@
|
| __ bind(&non_smi_result);
|
| // Allocate a heap number if needed.
|
| __ mov(ebx, Operand(eax)); // ebx: result
|
| - NearLabel skip_allocation;
|
| + Label skip_allocation;
|
| switch (mode_) {
|
| case OVERWRITE_LEFT:
|
| case OVERWRITE_RIGHT:
|
| @@ -1587,7 +1595,7 @@
|
| __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
|
| 1 * kPointerSize : 2 * kPointerSize));
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &skip_allocation, not_taken);
|
| + __ j(not_zero, &skip_allocation, Label::kNear);
|
| // Fall through!
|
| case NO_OVERWRITE:
|
| __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
|
| @@ -1666,8 +1674,6 @@
|
|
|
|
|
| void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
| - Label call_runtime;
|
| -
|
| if (op_ == Token::ADD) {
|
| // Handle string addition here, because it is the only operation
|
| // that does not do a ToNumber conversion on the operands.
|
| @@ -1677,18 +1683,18 @@
|
| Factory* factory = masm->isolate()->factory();
|
|
|
| // Convert odd ball arguments to numbers.
|
| - NearLabel check, done;
|
| + Label check, done;
|
| __ cmp(edx, factory->undefined_value());
|
| - __ j(not_equal, &check);
|
| + __ j(not_equal, &check, Label::kNear);
|
| if (Token::IsBitOp(op_)) {
|
| __ xor_(edx, Operand(edx));
|
| } else {
|
| __ mov(edx, Immediate(factory->nan_value()));
|
| }
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
| __ bind(&check);
|
| __ cmp(eax, factory->undefined_value());
|
| - __ j(not_equal, &done);
|
| + __ j(not_equal, &done, Label::kNear);
|
| if (Token::IsBitOp(op_)) {
|
| __ xor_(eax, Operand(eax));
|
| } else {
|
| @@ -1795,7 +1801,7 @@
|
| __ bind(&non_smi_result);
|
| // Allocate a heap number if needed.
|
| __ mov(ebx, Operand(eax)); // ebx: result
|
| - NearLabel skip_allocation;
|
| + Label skip_allocation;
|
| switch (mode_) {
|
| case OVERWRITE_LEFT:
|
| case OVERWRITE_RIGHT:
|
| @@ -1804,7 +1810,7 @@
|
| __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
|
| 1 * kPointerSize : 2 * kPointerSize));
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &skip_allocation, not_taken);
|
| + __ j(not_zero, &skip_allocation, Label::kNear);
|
| // Fall through!
|
| case NO_OVERWRITE:
|
| __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
|
| @@ -1995,7 +2001,7 @@
|
| __ bind(&non_smi_result);
|
| // Allocate a heap number if needed.
|
| __ mov(ebx, Operand(eax)); // ebx: result
|
| - NearLabel skip_allocation;
|
| + Label skip_allocation;
|
| switch (mode_) {
|
| case OVERWRITE_LEFT:
|
| case OVERWRITE_RIGHT:
|
| @@ -2004,7 +2010,7 @@
|
| __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
|
| 1 * kPointerSize : 2 * kPointerSize));
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &skip_allocation, not_taken);
|
| + __ j(not_zero, &skip_allocation, Label::kNear);
|
| // Fall through!
|
| case NO_OVERWRITE:
|
| __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
|
| @@ -2080,7 +2086,7 @@
|
|
|
| void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
| ASSERT(op_ == Token::ADD);
|
| - NearLabel left_not_string, call_runtime;
|
| + Label left_not_string, call_runtime;
|
|
|
| // Registers containing left and right operands respectively.
|
| Register left = edx;
|
| @@ -2088,9 +2094,9 @@
|
|
|
| // Test if left operand is a string.
|
| __ test(left, Immediate(kSmiTagMask));
|
| - __ j(zero, &left_not_string);
|
| + __ j(zero, &left_not_string, Label::kNear);
|
| __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx);
|
| - __ j(above_equal, &left_not_string);
|
| + __ j(above_equal, &left_not_string, Label::kNear);
|
|
|
| StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
|
| GenerateRegisterArgsPush(masm);
|
| @@ -2099,9 +2105,9 @@
|
| // Left operand is not a string, test right.
|
| __ bind(&left_not_string);
|
| __ test(right, Immediate(kSmiTagMask));
|
| - __ j(zero, &call_runtime);
|
| + __ j(zero, &call_runtime, Label::kNear);
|
| __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx);
|
| - __ j(above_equal, &call_runtime);
|
| + __ j(above_equal, &call_runtime, Label::kNear);
|
|
|
| StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
|
| GenerateRegisterArgsPush(masm);
|
| @@ -2122,7 +2128,7 @@
|
| // If the argument in edx is already an object, we skip the
|
| // allocation of a heap number.
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &skip_allocation, not_taken);
|
| + __ j(not_zero, &skip_allocation);
|
| // Allocate a heap number for the result. Keep eax and edx intact
|
| // for the possible runtime call.
|
| __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure);
|
| @@ -2138,7 +2144,7 @@
|
| // If the argument in eax is already an object, we skip the
|
| // allocation of a heap number.
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &skip_allocation, not_taken);
|
| + __ j(not_zero, &skip_allocation);
|
| // Fall through!
|
| case NO_OVERWRITE:
|
| // Allocate a heap number for the result. Keep eax and edx intact
|
| @@ -2182,11 +2188,11 @@
|
| const bool tagged = (argument_type_ == TAGGED);
|
| if (tagged) {
|
| // Test that eax is a number.
|
| - NearLabel input_not_smi;
|
| - NearLabel loaded;
|
| + Label input_not_smi;
|
| + Label loaded;
|
| __ mov(eax, Operand(esp, kPointerSize));
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &input_not_smi);
|
| + __ j(not_zero, &input_not_smi, Label::kNear);
|
| // Input is a smi. Untag and load it onto the FPU stack.
|
| // Then load the low and high words of the double into ebx, edx.
|
| STATIC_ASSERT(kSmiTagSize == 1);
|
| @@ -2197,7 +2203,7 @@
|
| __ fst_d(Operand(esp, 0));
|
| __ pop(edx);
|
| __ pop(ebx);
|
| - __ jmp(&loaded);
|
| + __ jmp(&loaded, Label::kNear);
|
| __ bind(&input_not_smi);
|
| // Check if input is a HeapNumber.
|
| __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
| @@ -2271,11 +2277,11 @@
|
| __ lea(ecx, Operand(ecx, ecx, times_2, 0));
|
| __ lea(ecx, Operand(eax, ecx, times_4, 0));
|
| // Check if cache matches: Double value is stored in uint32_t[2] array.
|
| - NearLabel cache_miss;
|
| + Label cache_miss;
|
| __ cmp(ebx, Operand(ecx, 0));
|
| - __ j(not_equal, &cache_miss);
|
| + __ j(not_equal, &cache_miss, Label::kNear);
|
| __ cmp(edx, Operand(ecx, kIntSize));
|
| - __ j(not_equal, &cache_miss);
|
| + __ j(not_equal, &cache_miss, Label::kNear);
|
| // Cache hit!
|
| __ mov(eax, Operand(ecx, 2 * kIntSize));
|
| if (tagged) {
|
| @@ -2373,7 +2379,7 @@
|
| // Both fsin and fcos require arguments in the range +/-2^63 and
|
| // return NaN for infinities and NaN. They can share all code except
|
| // the actual fsin/fcos operation.
|
| - NearLabel in_range, done;
|
| + Label in_range, done;
|
| // If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
| // work. We must reduce it to the appropriate range.
|
| __ mov(edi, edx);
|
| @@ -2381,11 +2387,11 @@
|
| int supported_exponent_limit =
|
| (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift;
|
| __ cmp(Operand(edi), Immediate(supported_exponent_limit));
|
| - __ j(below, &in_range, taken);
|
| + __ j(below, &in_range, Label::kNear);
|
| // Check for infinity and NaN. Both return NaN for sin.
|
| __ cmp(Operand(edi), Immediate(0x7ff00000));
|
| - NearLabel non_nan_result;
|
| - __ j(not_equal, &non_nan_result, taken);
|
| + Label non_nan_result;
|
| + __ j(not_equal, &non_nan_result, Label::kNear);
|
| // Input is +/-Infinity or NaN. Result is NaN.
|
| __ fstp(0);
|
| // NaN is represented by 0x7ff8000000000000.
|
| @@ -2393,7 +2399,7 @@
|
| __ push(Immediate(0));
|
| __ fld_d(Operand(esp, 0));
|
| __ add(Operand(esp), Immediate(2 * kPointerSize));
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
|
|
| __ bind(&non_nan_result);
|
|
|
| @@ -2404,19 +2410,19 @@
|
| __ fld(1);
|
| // FPU Stack: input, 2*pi, input.
|
| {
|
| - NearLabel no_exceptions;
|
| + Label no_exceptions;
|
| __ fwait();
|
| __ fnstsw_ax();
|
| // Clear if Illegal Operand or Zero Division exceptions are set.
|
| __ test(Operand(eax), Immediate(5));
|
| - __ j(zero, &no_exceptions);
|
| + __ j(zero, &no_exceptions, Label::kNear);
|
| __ fnclex();
|
| __ bind(&no_exceptions);
|
| }
|
|
|
| // Compute st(0) % st(1)
|
| {
|
| - NearLabel partial_remainder_loop;
|
| + Label partial_remainder_loop;
|
| __ bind(&partial_remainder_loop);
|
| __ fprem1();
|
| __ fwait();
|
| @@ -2455,58 +2461,6 @@
|
|
|
| // Input: edx, eax are the left and right objects of a bit op.
|
| // Output: eax, ecx are left and right integers for a bit op.
|
| -void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm,
|
| - TypeInfo type_info,
|
| - bool use_sse3,
|
| - Label* conversion_failure) {
|
| - // Check float operands.
|
| - Label arg1_is_object, check_undefined_arg1;
|
| - Label arg2_is_object, check_undefined_arg2;
|
| - Label load_arg2, done;
|
| -
|
| - if (!type_info.IsDouble()) {
|
| - if (!type_info.IsSmi()) {
|
| - __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &arg1_is_object);
|
| - } else {
|
| - if (FLAG_debug_code) __ AbortIfNotSmi(edx);
|
| - }
|
| - __ SmiUntag(edx);
|
| - __ jmp(&load_arg2);
|
| - }
|
| -
|
| - __ bind(&arg1_is_object);
|
| -
|
| - // Get the untagged integer version of the edx heap number in ecx.
|
| - IntegerConvert(masm, edx, type_info, use_sse3, conversion_failure);
|
| - __ mov(edx, ecx);
|
| -
|
| - // Here edx has the untagged integer, eax has a Smi or a heap number.
|
| - __ bind(&load_arg2);
|
| - if (!type_info.IsDouble()) {
|
| - // Test if arg2 is a Smi.
|
| - if (!type_info.IsSmi()) {
|
| - __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &arg2_is_object);
|
| - } else {
|
| - if (FLAG_debug_code) __ AbortIfNotSmi(eax);
|
| - }
|
| - __ SmiUntag(eax);
|
| - __ mov(ecx, eax);
|
| - __ jmp(&done);
|
| - }
|
| -
|
| - __ bind(&arg2_is_object);
|
| -
|
| - // Get the untagged integer version of the eax heap number in ecx.
|
| - IntegerConvert(masm, eax, type_info, use_sse3, conversion_failure);
|
| - __ bind(&done);
|
| - __ mov(eax, edx);
|
| -}
|
| -
|
| -
|
| -// Input: edx, eax are the left and right objects of a bit op.
|
| -// Output: eax, ecx are left and right integers for a bit op.
|
| void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
|
| bool use_sse3,
|
| Label* conversion_failure) {
|
| @@ -2536,11 +2490,7 @@
|
| __ j(not_equal, &check_undefined_arg1);
|
|
|
| // Get the untagged integer version of the edx heap number in ecx.
|
| - IntegerConvert(masm,
|
| - edx,
|
| - TypeInfo::Unknown(),
|
| - use_sse3,
|
| - conversion_failure);
|
| + IntegerConvert(masm, edx, use_sse3, conversion_failure);
|
| __ mov(edx, ecx);
|
|
|
| // Here edx has the untagged integer, eax has a Smi or a heap number.
|
| @@ -2567,28 +2517,12 @@
|
| __ j(not_equal, &check_undefined_arg2);
|
|
|
| // Get the untagged integer version of the eax heap number in ecx.
|
| - IntegerConvert(masm,
|
| - eax,
|
| - TypeInfo::Unknown(),
|
| - use_sse3,
|
| - conversion_failure);
|
| + IntegerConvert(masm, eax, use_sse3, conversion_failure);
|
| __ bind(&done);
|
| __ mov(eax, edx);
|
| }
|
|
|
|
|
| -void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
|
| - TypeInfo type_info,
|
| - bool use_sse3,
|
| - Label* conversion_failure) {
|
| - if (type_info.IsNumber()) {
|
| - LoadNumbersAsIntegers(masm, type_info, use_sse3, conversion_failure);
|
| - } else {
|
| - LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure);
|
| - }
|
| -}
|
| -
|
| -
|
| void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm,
|
| bool use_sse3,
|
| Label* not_int32) {
|
| @@ -2598,12 +2532,12 @@
|
|
|
| void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
|
| Register number) {
|
| - NearLabel load_smi, done;
|
| + Label load_smi, done;
|
|
|
| __ test(number, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi, not_taken);
|
| + __ j(zero, &load_smi, Label::kNear);
|
| __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
|
|
| __ bind(&load_smi);
|
| __ SmiUntag(number);
|
| @@ -2616,18 +2550,20 @@
|
|
|
|
|
| void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
|
| - NearLabel load_smi_edx, load_eax, load_smi_eax, done;
|
| + Label load_smi_edx, load_eax, load_smi_eax, done;
|
| // Load operand in edx into xmm0.
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
|
| + // Argument in edx is a smi.
|
| + __ j(zero, &load_smi_edx, Label::kNear);
|
| __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
|
|
|
| __ bind(&load_eax);
|
| // Load operand in eax into xmm1.
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
|
| + // Argument in eax is a smi.
|
| + __ j(zero, &load_smi_eax, Label::kNear);
|
| __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
|
|
| __ bind(&load_smi_edx);
|
| __ SmiUntag(edx); // Untag smi before converting to float.
|
| @@ -2646,10 +2582,11 @@
|
|
|
| void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
|
| Label* not_numbers) {
|
| - NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
|
| + Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
|
| // Load operand in edx into xmm0, or branch to not_numbers.
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
|
| + // Argument in edx is a smi.
|
| + __ j(zero, &load_smi_edx, Label::kNear);
|
| Factory* factory = masm->isolate()->factory();
|
| __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map());
|
| __ j(not_equal, not_numbers); // Argument in edx is not a number.
|
| @@ -2657,9 +2594,10 @@
|
| __ bind(&load_eax);
|
| // Load operand in eax into xmm1, or branch to not_numbers.
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
|
| + // Argument in eax is a smi.
|
| + __ j(zero, &load_smi_eax, Label::kNear);
|
| __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map());
|
| - __ j(equal, &load_float_eax);
|
| + __ j(equal, &load_float_eax, Label::kNear);
|
| __ jmp(not_numbers); // Argument in eax is not a number.
|
| __ bind(&load_smi_edx);
|
| __ SmiUntag(edx); // Untag smi before converting to float.
|
| @@ -2670,7 +2608,7 @@
|
| __ SmiUntag(eax); // Untag smi before converting to float.
|
| __ cvtsi2sd(xmm1, Operand(eax));
|
| __ SmiTag(eax); // Retag smi for heap number overwriting test.
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
| __ bind(&load_float_eax);
|
| __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
|
| __ bind(&done);
|
| @@ -2711,14 +2649,14 @@
|
| void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
|
| Register scratch,
|
| ArgLocation arg_location) {
|
| - NearLabel load_smi_1, load_smi_2, done_load_1, done;
|
| + Label load_smi_1, load_smi_2, done_load_1, done;
|
| if (arg_location == ARGS_IN_REGISTERS) {
|
| __ mov(scratch, edx);
|
| } else {
|
| __ mov(scratch, Operand(esp, 2 * kPointerSize));
|
| }
|
| __ test(scratch, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_1, not_taken);
|
| + __ j(zero, &load_smi_1, Label::kNear);
|
| __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
|
| __ bind(&done_load_1);
|
|
|
| @@ -2728,9 +2666,9 @@
|
| __ mov(scratch, Operand(esp, 1 * kPointerSize));
|
| }
|
| __ test(scratch, Immediate(kSmiTagMask));
|
| - __ j(zero, &load_smi_2, not_taken);
|
| + __ j(zero, &load_smi_2, Label::kNear);
|
| __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
|
|
| __ bind(&load_smi_1);
|
| __ SmiUntag(scratch);
|
| @@ -2770,11 +2708,11 @@
|
| void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
|
| Label* non_float,
|
| Register scratch) {
|
| - NearLabel test_other, done;
|
| + Label test_other, done;
|
| // Test if both operands are floats or smi -> scratch=k_is_float;
|
| // Otherwise scratch = k_not_float.
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(zero, &test_other, not_taken); // argument in edx is OK
|
| + __ j(zero, &test_other, Label::kNear); // argument in edx is OK
|
| __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
|
| Factory* factory = masm->isolate()->factory();
|
| __ cmp(scratch, factory->heap_number_map());
|
| @@ -2782,7 +2720,7 @@
|
|
|
| __ bind(&test_other);
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(zero, &done); // argument in eax is OK
|
| + __ j(zero, &done, Label::kNear); // argument in eax is OK
|
| __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
|
| __ cmp(scratch, factory->heap_number_map());
|
| __ j(not_equal, non_float); // argument in eax is not a number -> NaN
|
| @@ -2847,20 +2785,20 @@
|
| __ mov(edx, eax);
|
|
|
| // Get absolute value of exponent.
|
| - NearLabel no_neg;
|
| + Label no_neg;
|
| __ cmp(eax, 0);
|
| - __ j(greater_equal, &no_neg);
|
| + __ j(greater_equal, &no_neg, Label::kNear);
|
| __ neg(eax);
|
| __ bind(&no_neg);
|
|
|
| // Load xmm1 with 1.
|
| __ movsd(xmm1, xmm3);
|
| - NearLabel while_true;
|
| - NearLabel no_multiply;
|
| + Label while_true;
|
| + Label no_multiply;
|
|
|
| __ bind(&while_true);
|
| __ shr(eax, 1);
|
| - __ j(not_carry, &no_multiply);
|
| + __ j(not_carry, &no_multiply, Label::kNear);
|
| __ mulsd(xmm1, xmm0);
|
| __ bind(&no_multiply);
|
| __ mulsd(xmm0, xmm0);
|
| @@ -2891,13 +2829,13 @@
|
| __ ucomisd(xmm1, xmm1);
|
| __ j(parity_even, &call_runtime);
|
|
|
| - NearLabel base_not_smi;
|
| - NearLabel handle_special_cases;
|
| + Label base_not_smi;
|
| + Label handle_special_cases;
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &base_not_smi);
|
| + __ j(not_zero, &base_not_smi, Label::kNear);
|
| __ SmiUntag(edx);
|
| __ cvtsi2sd(xmm0, Operand(edx));
|
| - __ jmp(&handle_special_cases);
|
| + __ jmp(&handle_special_cases, Label::kNear);
|
|
|
| __ bind(&base_not_smi);
|
| __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
|
| @@ -2912,7 +2850,7 @@
|
|
|
| // base is in xmm0 and exponent is in xmm1.
|
| __ bind(&handle_special_cases);
|
| - NearLabel not_minus_half;
|
| + Label not_minus_half;
|
| // Test for -0.5.
|
| // Load xmm2 with -0.5.
|
| __ mov(ecx, Immediate(0xBF000000));
|
| @@ -2920,7 +2858,7 @@
|
| __ cvtss2sd(xmm2, xmm2);
|
| // xmm2 now has -0.5.
|
| __ ucomisd(xmm2, xmm1);
|
| - __ j(not_equal, ¬_minus_half);
|
| + __ j(not_equal, ¬_minus_half, Label::kNear);
|
|
|
| // Calculates reciprocal of square root.
|
| // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
|
| @@ -2967,20 +2905,20 @@
|
| // Check that the key is a smi.
|
| Label slow;
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &slow, not_taken);
|
| + __ j(not_zero, &slow);
|
|
|
| // Check if the calling frame is an arguments adaptor frame.
|
| - NearLabel adaptor;
|
| + Label adaptor;
|
| __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
| __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
|
| __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
| - __ j(equal, &adaptor);
|
| + __ j(equal, &adaptor, Label::kNear);
|
|
|
| // Check index against formal parameters count limit passed in
|
| // through register eax. Use unsigned comparison to get negative
|
| // check for free.
|
| __ cmp(edx, Operand(eax));
|
| - __ j(above_equal, &slow, not_taken);
|
| + __ j(above_equal, &slow);
|
|
|
| // Read the argument from the stack and return it.
|
| STATIC_ASSERT(kSmiTagSize == 1);
|
| @@ -2996,7 +2934,7 @@
|
| __ bind(&adaptor);
|
| __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| __ cmp(edx, Operand(ecx));
|
| - __ j(above_equal, &slow, not_taken);
|
| + __ j(above_equal, &slow);
|
|
|
| // Read the argument from the stack and return it.
|
| STATIC_ASSERT(kSmiTagSize == 1);
|
| @@ -3047,10 +2985,10 @@
|
|
|
| // Try the new space allocation. Start out with computing the size of
|
| // the arguments object and the elements array.
|
| - NearLabel add_arguments_object;
|
| + Label add_arguments_object;
|
| __ bind(&try_allocate);
|
| __ test(ecx, Operand(ecx));
|
| - __ j(zero, &add_arguments_object);
|
| + __ j(zero, &add_arguments_object, Label::kNear);
|
| __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
|
| __ bind(&add_arguments_object);
|
| __ add(Operand(ecx), Immediate(GetArgumentsObjectSize()));
|
| @@ -3106,7 +3044,7 @@
|
| __ SmiUntag(ecx);
|
|
|
| // Copy the fixed array slots.
|
| - NearLabel loop;
|
| + Label loop;
|
| __ bind(&loop);
|
| __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
|
| __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
|
| @@ -3159,7 +3097,7 @@
|
| ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
|
| __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
|
| __ test(ebx, Operand(ebx));
|
| - __ j(zero, &runtime, not_taken);
|
| + __ j(zero, &runtime);
|
|
|
| // Check that the first argument is a JSRegExp object.
|
| __ mov(eax, Operand(esp, kJSRegExpOffset));
|
| @@ -3343,16 +3281,16 @@
|
|
|
| // Argument 4: End of string data
|
| // Argument 3: Start of string data
|
| - NearLabel setup_two_byte, setup_rest;
|
| + Label setup_two_byte, setup_rest;
|
| __ test(edi, Operand(edi));
|
| __ mov(edi, FieldOperand(eax, String::kLengthOffset));
|
| - __ j(zero, &setup_two_byte);
|
| + __ j(zero, &setup_two_byte, Label::kNear);
|
| __ SmiUntag(edi);
|
| __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
|
| __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
|
| __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
|
| __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
|
| - __ jmp(&setup_rest);
|
| + __ jmp(&setup_rest, Label::kNear);
|
|
|
| __ bind(&setup_two_byte);
|
| STATIC_ASSERT(kSmiTag == 0);
|
| @@ -3380,10 +3318,10 @@
|
| // Check the result.
|
| Label success;
|
| __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS);
|
| - __ j(equal, &success, taken);
|
| + __ j(equal, &success);
|
| Label failure;
|
| __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
|
| - __ j(equal, &failure, taken);
|
| + __ j(equal, &failure);
|
| __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
|
| // If not exception it can only be retry. Handle that in the runtime system.
|
| __ j(not_equal, &runtime);
|
| @@ -3466,12 +3404,12 @@
|
| // ebx: last_match_info backing store (FixedArray)
|
| // ecx: offsets vector
|
| // edx: number of capture registers
|
| - NearLabel next_capture, done;
|
| + Label next_capture, done;
|
| // Capture register counter starts from number of capture registers and
|
| // counts down until wraping after zero.
|
| __ bind(&next_capture);
|
| __ sub(Operand(edx), Immediate(1));
|
| - __ j(negative, &done);
|
| + __ j(negative, &done, Label::kNear);
|
| // Read the value from the static offsets vector buffer.
|
| __ mov(edi, Operand(ecx, edx, times_int_size, 0));
|
| __ SmiTag(edi);
|
| @@ -3498,7 +3436,7 @@
|
| void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
|
| const int kMaxInlineLength = 100;
|
| Label slowcase;
|
| - NearLabel done;
|
| + Label done;
|
| __ mov(ebx, Operand(esp, kPointerSize * 3));
|
| __ test(ebx, Immediate(kSmiTagMask));
|
| __ j(not_zero, &slowcase);
|
| @@ -3564,7 +3502,7 @@
|
| Label loop;
|
| __ test(ecx, Operand(ecx));
|
| __ bind(&loop);
|
| - __ j(less_equal, &done); // Jump if ecx is negative or zero.
|
| + __ j(less_equal, &done, Label::kNear); // Jump if ecx is negative or zero.
|
| __ sub(Operand(ecx), Immediate(1));
|
| __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx);
|
| __ jmp(&loop);
|
| @@ -3605,19 +3543,19 @@
|
| // number string cache for smis is just the smi value, and the hash for
|
| // doubles is the xor of the upper and lower words. See
|
| // Heap::GetNumberStringCache.
|
| - NearLabel smi_hash_calculated;
|
| - NearLabel load_result_from_cache;
|
| + Label smi_hash_calculated;
|
| + Label load_result_from_cache;
|
| if (object_is_smi) {
|
| __ mov(scratch, object);
|
| __ SmiUntag(scratch);
|
| } else {
|
| - NearLabel not_smi, hash_calculated;
|
| + Label not_smi;
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ test(object, Immediate(kSmiTagMask));
|
| - __ j(not_zero, ¬_smi);
|
| + __ j(not_zero, ¬_smi, Label::kNear);
|
| __ mov(scratch, object);
|
| __ SmiUntag(scratch);
|
| - __ jmp(&smi_hash_calculated);
|
| + __ jmp(&smi_hash_calculated, Label::kNear);
|
| __ bind(¬_smi);
|
| __ cmp(FieldOperand(object, HeapObject::kMapOffset),
|
| masm->isolate()->factory()->heap_number_map());
|
| @@ -3648,7 +3586,7 @@
|
| }
|
| __ j(parity_even, not_found); // Bail out if NaN is involved.
|
| __ j(not_equal, not_found); // The cache did not contain this value.
|
| - __ jmp(&load_result_from_cache);
|
| + __ jmp(&load_result_from_cache, Label::kNear);
|
| }
|
|
|
| __ bind(&smi_hash_calculated);
|
| @@ -3708,7 +3646,7 @@
|
| __ mov(ecx, Operand(edx));
|
| __ or_(ecx, Operand(eax));
|
| __ test(ecx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &non_smi, not_taken);
|
| + __ j(not_zero, &non_smi);
|
| __ sub(edx, Operand(eax)); // Return on the result of the subtraction.
|
| __ j(no_overflow, &smi_done);
|
| __ not_(edx); // Correct sign in case of overflow. edx is never 0 here.
|
| @@ -3736,9 +3674,9 @@
|
| if (cc_ != equal) {
|
| // Check for undefined. undefined OP undefined is false even though
|
| // undefined == undefined.
|
| - NearLabel check_for_nan;
|
| + Label check_for_nan;
|
| __ cmp(edx, masm->isolate()->factory()->undefined_value());
|
| - __ j(not_equal, &check_for_nan);
|
| + __ j(not_equal, &check_for_nan, Label::kNear);
|
| __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_))));
|
| __ ret(0);
|
| __ bind(&check_for_nan);
|
| @@ -3751,10 +3689,10 @@
|
| __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| __ ret(0);
|
| } else {
|
| - NearLabel heap_number;
|
| + Label heap_number;
|
| __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
|
| Immediate(masm->isolate()->factory()->heap_number_map()));
|
| - __ j(equal, &heap_number);
|
| + __ j(equal, &heap_number, Label::kNear);
|
| if (cc_ != equal) {
|
| // Call runtime on identical JSObjects. Otherwise return equal.
|
| __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
| @@ -3786,8 +3724,8 @@
|
| __ setcc(above_equal, eax);
|
| __ ret(0);
|
| } else {
|
| - NearLabel nan;
|
| - __ j(above_equal, &nan);
|
| + Label nan;
|
| + __ j(above_equal, &nan, Label::kNear);
|
| __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| __ ret(0);
|
| __ bind(&nan);
|
| @@ -3803,7 +3741,7 @@
|
| // Non-strict object equality is slower, so it is handled later in the stub.
|
| if (cc_ == equal && strict_) {
|
| Label slow; // Fallthrough label.
|
| - NearLabel not_smis;
|
| + Label not_smis;
|
| // If we're doing a strict equality comparison, we don't have to do
|
| // type conversion, so we generate code to do fast comparison for objects
|
| // and oddballs. Non-smi numbers and strings still go through the usual
|
| @@ -3815,7 +3753,7 @@
|
| __ mov(ecx, Immediate(kSmiTagMask));
|
| __ and_(ecx, Operand(eax));
|
| __ test(ecx, Operand(edx));
|
| - __ j(not_zero, ¬_smis);
|
| + __ j(not_zero, ¬_smis, Label::kNear);
|
| // One operand is a smi.
|
|
|
| // Check whether the non-smi is a heap number.
|
| @@ -3844,13 +3782,13 @@
|
|
|
| // Get the type of the first operand.
|
| // If the first object is a JS object, we have done pointer comparison.
|
| - NearLabel first_non_object;
|
| + Label first_non_object;
|
| STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
| - __ j(below, &first_non_object);
|
| + __ j(below, &first_non_object, Label::kNear);
|
|
|
| // Return non-zero (eax is not zero)
|
| - NearLabel return_not_equal;
|
| + Label return_not_equal;
|
| STATIC_ASSERT(kHeapObjectTag != 0);
|
| __ bind(&return_not_equal);
|
| __ ret(0);
|
| @@ -3883,7 +3821,7 @@
|
| __ ucomisd(xmm0, xmm1);
|
|
|
| // Don't base result on EFLAGS when a NaN is involved.
|
| - __ j(parity_even, &unordered, not_taken);
|
| + __ j(parity_even, &unordered);
|
| // Return a result of -1, 0, or 1, based on EFLAGS.
|
| __ mov(eax, 0); // equal
|
| __ mov(ecx, Immediate(Smi::FromInt(1)));
|
| @@ -3899,12 +3837,12 @@
|
| __ FCmp();
|
|
|
| // Don't base result on EFLAGS when a NaN is involved.
|
| - __ j(parity_even, &unordered, not_taken);
|
| + __ j(parity_even, &unordered);
|
|
|
| - NearLabel below_label, above_label;
|
| + Label below_label, above_label;
|
| // Return a result of -1, 0, or 1, based on EFLAGS.
|
| - __ j(below, &below_label, not_taken);
|
| - __ j(above, &above_label, not_taken);
|
| + __ j(below, &below_label);
|
| + __ j(above, &above_label);
|
|
|
| __ Set(eax, Immediate(0));
|
| __ ret(0);
|
| @@ -3951,12 +3889,20 @@
|
| &check_unequal_objects);
|
|
|
| // Inline comparison of ascii strings.
|
| - StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
|
| + if (cc_ == equal) {
|
| + StringCompareStub::GenerateFlatAsciiStringEquals(masm,
|
| edx,
|
| eax,
|
| ecx,
|
| - ebx,
|
| - edi);
|
| + ebx);
|
| + } else {
|
| + StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
|
| + edx,
|
| + eax,
|
| + ecx,
|
| + ebx,
|
| + edi);
|
| + }
|
| #ifdef DEBUG
|
| __ Abort("Unexpected fall-through from string comparison");
|
| #endif
|
| @@ -3966,8 +3912,8 @@
|
| // Non-strict equality. Objects are unequal if
|
| // they are both JSObjects and not undetectable,
|
| // and their pointers are different.
|
| - NearLabel not_both_objects;
|
| - NearLabel return_unequal;
|
| + Label not_both_objects;
|
| + Label return_unequal;
|
| // At most one is a smi, so we can test for smi by adding the two.
|
| // A smi plus a heap object has the low bit set, a heap object plus
|
| // a heap object has the low bit clear.
|
| @@ -3975,20 +3921,20 @@
|
| STATIC_ASSERT(kSmiTagMask == 1);
|
| __ lea(ecx, Operand(eax, edx, times_1, 0));
|
| __ test(ecx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, ¬_both_objects);
|
| + __ j(not_zero, ¬_both_objects, Label::kNear);
|
| __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
| - __ j(below, ¬_both_objects);
|
| + __ j(below, ¬_both_objects, Label::kNear);
|
| __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx);
|
| - __ j(below, ¬_both_objects);
|
| + __ j(below, ¬_both_objects, Label::kNear);
|
| // We do not bail out after this point. Both are JSObjects, and
|
| // they are equal if and only if both are undetectable.
|
| // The and of the undetectable flags is 1 if and only if they are equal.
|
| __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
|
| 1 << Map::kIsUndetectable);
|
| - __ j(zero, &return_unequal);
|
| + __ j(zero, &return_unequal, Label::kNear);
|
| __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
|
| 1 << Map::kIsUndetectable);
|
| - __ j(zero, &return_unequal);
|
| + __ j(zero, &return_unequal, Label::kNear);
|
| // The objects are both undetectable, so they both compare as the value
|
| // undefined, and are equal.
|
| __ Set(eax, Immediate(EQUAL));
|
| @@ -4054,7 +4000,7 @@
|
|
|
| // Check if receiver is a smi (which is a number value).
|
| __ test(eax, Immediate(kSmiTagMask));
|
| - __ j(zero, &receiver_is_value, not_taken);
|
| + __ j(zero, &receiver_is_value);
|
|
|
| // Check if the receiver is a valid JS object.
|
| __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi);
|
| @@ -4077,10 +4023,10 @@
|
|
|
| // Check that the function really is a JavaScript function.
|
| __ test(edi, Immediate(kSmiTagMask));
|
| - __ j(zero, &slow, not_taken);
|
| + __ j(zero, &slow);
|
| // Goto slow case if we do not have a function.
|
| __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
|
| - __ j(not_equal, &slow, not_taken);
|
| + __ j(not_equal, &slow);
|
|
|
| // Fast-case: Just invoke the function.
|
| ParameterCount actual(argc_);
|
| @@ -4161,9 +4107,9 @@
|
| // Make sure we're not trying to return 'the hole' from the runtime
|
| // call as this may lead to crashes in the IC code later.
|
| if (FLAG_debug_code) {
|
| - NearLabel okay;
|
| + Label okay;
|
| __ cmp(eax, masm->isolate()->factory()->the_hole_value());
|
| - __ j(not_equal, &okay);
|
| + __ j(not_equal, &okay, Label::kNear);
|
| __ int3();
|
| __ bind(&okay);
|
| }
|
| @@ -4174,7 +4120,7 @@
|
| __ lea(ecx, Operand(eax, 1));
|
| // Lower 2 bits of ecx are 0 iff eax has failure tag.
|
| __ test(ecx, Immediate(kFailureTagMask));
|
| - __ j(zero, &failure_returned, not_taken);
|
| + __ j(zero, &failure_returned);
|
|
|
| ExternalReference pending_exception_address(
|
| Isolate::k_pending_exception_address, masm->isolate());
|
| @@ -4185,10 +4131,10 @@
|
| __ push(edx);
|
| __ mov(edx, Operand::StaticVariable(
|
| ExternalReference::the_hole_value_location(masm->isolate())));
|
| - NearLabel okay;
|
| + Label okay;
|
| __ cmp(edx, Operand::StaticVariable(pending_exception_address));
|
| // Cannot use check here as it attempts to generate call into runtime.
|
| - __ j(equal, &okay);
|
| + __ j(equal, &okay, Label::kNear);
|
| __ int3();
|
| __ bind(&okay);
|
| __ pop(edx);
|
| @@ -4205,7 +4151,7 @@
|
| // If the returned exception is RETRY_AFTER_GC continue at retry label
|
| STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
|
| __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
|
| - __ j(zero, &retry, taken);
|
| + __ j(zero, &retry);
|
|
|
| // Special handling of out of memory exceptions.
|
| __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
|
| @@ -4330,7 +4276,12 @@
|
| __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
|
| __ j(not_equal, ¬_outermost_js);
|
| __ mov(Operand::StaticVariable(js_entry_sp), ebp);
|
| + __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
|
| + Label cont;
|
| + __ jmp(&cont);
|
| __ bind(¬_outermost_js);
|
| + __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
|
| + __ bind(&cont);
|
| #endif
|
|
|
| // Call a faked try-block that does the invoke.
|
| @@ -4376,23 +4327,20 @@
|
| __ call(Operand(edx));
|
|
|
| // Unlink this frame from the handler chain.
|
| - __ pop(Operand::StaticVariable(ExternalReference(
|
| - Isolate::k_handler_address,
|
| - masm->isolate())));
|
| - // Pop next_sp.
|
| - __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
|
| + __ PopTryHandler();
|
|
|
| + __ bind(&exit);
|
| #ifdef ENABLE_LOGGING_AND_PROFILING
|
| - // If current EBP value is the same as js_entry_sp value, it means that
|
| - // the current function is the outermost.
|
| - __ cmp(ebp, Operand::StaticVariable(js_entry_sp));
|
| + // Check if the current stack frame is marked as the outermost JS frame.
|
| + __ pop(ebx);
|
| + __ cmp(Operand(ebx),
|
| + Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
|
| __ j(not_equal, ¬_outermost_js_2);
|
| __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
|
| __ bind(¬_outermost_js_2);
|
| #endif
|
|
|
| // Restore the top frame descriptor from the stack.
|
| - __ bind(&exit);
|
| __ pop(Operand::StaticVariable(ExternalReference(
|
| Isolate::k_c_entry_fp_address,
|
| masm->isolate())));
|
| @@ -4459,22 +4407,22 @@
|
|
|
| // Check that the left hand is a JS object.
|
| __ test(object, Immediate(kSmiTagMask));
|
| - __ j(zero, ¬_js_object, not_taken);
|
| + __ j(zero, ¬_js_object);
|
| __ IsObjectJSObjectType(object, map, scratch, ¬_js_object);
|
|
|
| // If there is a call site cache don't look in the global cache, but do the
|
| // real lookup and update the call site cache.
|
| if (!HasCallSiteInlineCheck()) {
|
| // Look up the function and the map in the instanceof cache.
|
| - NearLabel miss;
|
| + Label miss;
|
| __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
|
| __ cmp(function,
|
| Operand::StaticArray(scratch, times_pointer_size, roots_address));
|
| - __ j(not_equal, &miss);
|
| + __ j(not_equal, &miss, Label::kNear);
|
| __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
|
| __ cmp(map, Operand::StaticArray(
|
| scratch, times_pointer_size, roots_address));
|
| - __ j(not_equal, &miss);
|
| + __ j(not_equal, &miss, Label::kNear);
|
| __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
|
| __ mov(eax, Operand::StaticArray(
|
| scratch, times_pointer_size, roots_address));
|
| @@ -4487,7 +4435,7 @@
|
|
|
| // Check that the function prototype is a JS object.
|
| __ test(prototype, Immediate(kSmiTagMask));
|
| - __ j(zero, &slow, not_taken);
|
| + __ j(zero, &slow);
|
| __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
|
|
|
| // Update the global instanceof or call site inlined cache with the current
|
| @@ -4517,13 +4465,13 @@
|
| // Loop through the prototype chain of the object looking for the function
|
| // prototype.
|
| __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset));
|
| - NearLabel loop, is_instance, is_not_instance;
|
| + Label loop, is_instance, is_not_instance;
|
| __ bind(&loop);
|
| __ cmp(scratch, Operand(prototype));
|
| - __ j(equal, &is_instance);
|
| + __ j(equal, &is_instance, Label::kNear);
|
| Factory* factory = masm->isolate()->factory();
|
| __ cmp(Operand(scratch), Immediate(factory->null_value()));
|
| - __ j(equal, &is_not_instance);
|
| + __ j(equal, &is_not_instance, Label::kNear);
|
| __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
|
| __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
|
| __ jmp(&loop);
|
| @@ -4577,9 +4525,9 @@
|
| // Before null, smi and string value checks, check that the rhs is a function
|
| // as for a non-function rhs an exception needs to be thrown.
|
| __ test(function, Immediate(kSmiTagMask));
|
| - __ j(zero, &slow, not_taken);
|
| + __ j(zero, &slow);
|
| __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
|
| - __ j(not_equal, &slow, not_taken);
|
| + __ j(not_equal, &slow);
|
|
|
| // Null is not instance of anything.
|
| __ cmp(object, factory->null_value());
|
| @@ -4590,7 +4538,7 @@
|
| __ bind(&object_not_null);
|
| // Smi values is not instance of anything.
|
| __ test(object, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &object_not_null_or_smi, not_taken);
|
| + __ j(not_zero, &object_not_null_or_smi);
|
| __ Set(eax, Immediate(Smi::FromInt(1)));
|
| __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
|
|
|
| @@ -4620,11 +4568,11 @@
|
| __ push(function);
|
| __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
|
| __ LeaveInternalFrame();
|
| - NearLabel true_value, done;
|
| + Label true_value, done;
|
| __ test(eax, Operand(eax));
|
| - __ j(zero, &true_value);
|
| + __ j(zero, &true_value, Label::kNear);
|
| __ mov(eax, factory->false_value());
|
| - __ jmp(&done);
|
| + __ jmp(&done, Label::kNear);
|
| __ bind(&true_value);
|
| __ mov(eax, factory->true_value());
|
| __ bind(&done);
|
| @@ -4803,7 +4751,7 @@
|
| __ CheckMap(index_,
|
| masm->isolate()->factory()->heap_number_map(),
|
| index_not_number_,
|
| - true);
|
| + DONT_DO_SMI_CHECK);
|
| call_helper.BeforeCall(masm);
|
| __ push(object_);
|
| __ push(index_);
|
| @@ -4862,7 +4810,7 @@
|
| __ test(code_,
|
| Immediate(kSmiTagMask |
|
| ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
|
| - __ j(not_zero, &slow_case_, not_taken);
|
| + __ j(not_zero, &slow_case_);
|
|
|
| Factory* factory = masm->isolate()->factory();
|
| __ Set(result_, Immediate(factory->single_character_string_cache()));
|
| @@ -4874,7 +4822,7 @@
|
| code_, times_half_pointer_size,
|
| FixedArray::kHeaderSize));
|
| __ cmp(result_, factory->undefined_value());
|
| - __ j(equal, &slow_case_, not_taken);
|
| + __ j(equal, &slow_case_);
|
| __ bind(&exit_);
|
| }
|
|
|
| @@ -4953,11 +4901,11 @@
|
| // eax: first string
|
| // edx: second string
|
| // Check if either of the strings are empty. In that case return the other.
|
| - NearLabel second_not_zero_length, both_not_zero_length;
|
| + Label second_not_zero_length, both_not_zero_length;
|
| __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ test(ecx, Operand(ecx));
|
| - __ j(not_zero, &second_not_zero_length);
|
| + __ j(not_zero, &second_not_zero_length, Label::kNear);
|
| // Second string is empty, result is first string which is already in eax.
|
| Counters* counters = masm->isolate()->counters();
|
| __ IncrementCounter(counters->string_add_native(), 1);
|
| @@ -4966,7 +4914,7 @@
|
| __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ test(ebx, Operand(ebx));
|
| - __ j(not_zero, &both_not_zero_length);
|
| + __ j(not_zero, &both_not_zero_length, Label::kNear);
|
| // First string is empty, result is second string which is in edx.
|
| __ mov(eax, edx);
|
| __ IncrementCounter(counters->string_add_native(), 1);
|
| @@ -5240,7 +5188,7 @@
|
| Register count,
|
| Register scratch,
|
| bool ascii) {
|
| - NearLabel loop;
|
| + Label loop;
|
| __ bind(&loop);
|
| // This loop just copies one character at a time, as it is only used for very
|
| // short strings.
|
| @@ -5287,9 +5235,9 @@
|
| }
|
|
|
| // Don't enter the rep movs if there are less than 4 bytes to copy.
|
| - NearLabel last_bytes;
|
| + Label last_bytes;
|
| __ test(count, Immediate(~3));
|
| - __ j(zero, &last_bytes);
|
| + __ j(zero, &last_bytes, Label::kNear);
|
|
|
| // Copy from edi to esi using rep movs instruction.
|
| __ mov(scratch, count);
|
| @@ -5307,7 +5255,7 @@
|
| __ j(zero, &done);
|
|
|
| // Copy remaining characters.
|
| - NearLabel loop;
|
| + Label loop;
|
| __ bind(&loop);
|
| __ mov_b(scratch, Operand(src, 0));
|
| __ mov_b(Operand(dest, 0), scratch);
|
| @@ -5333,11 +5281,11 @@
|
|
|
| // Make sure that both characters are not digits as such strings has a
|
| // different hash algorithm. Don't try to look for these in the symbol table.
|
| - NearLabel not_array_index;
|
| + Label not_array_index;
|
| __ mov(scratch, c1);
|
| __ sub(Operand(scratch), Immediate(static_cast<int>('0')));
|
| __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0')));
|
| - __ j(above, ¬_array_index);
|
| + __ j(above, ¬_array_index, Label::kNear);
|
| __ mov(scratch, c2);
|
| __ sub(Operand(scratch), Immediate(static_cast<int>('0')));
|
| __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0')));
|
| @@ -5495,9 +5443,9 @@
|
| __ add(hash, Operand(scratch));
|
|
|
| // if (hash == 0) hash = 27;
|
| - NearLabel hash_not_zero;
|
| + Label hash_not_zero;
|
| __ test(hash, Operand(hash));
|
| - __ j(not_zero, &hash_not_zero);
|
| + __ j(not_zero, &hash_not_zero, Label::kNear);
|
| __ mov(hash, Immediate(27));
|
| __ bind(&hash_not_zero);
|
| }
|
| @@ -5652,28 +5600,60 @@
|
| }
|
|
|
|
|
| +void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
|
| + Register left,
|
| + Register right,
|
| + Register scratch1,
|
| + Register scratch2) {
|
| + Register length = scratch1;
|
| +
|
| + // Compare lengths.
|
| + Label strings_not_equal, check_zero_length;
|
| + __ mov(length, FieldOperand(left, String::kLengthOffset));
|
| + __ cmp(length, FieldOperand(right, String::kLengthOffset));
|
| + __ j(equal, &check_zero_length, Label::kNear);
|
| + __ bind(&strings_not_equal);
|
| + __ Set(eax, Immediate(Smi::FromInt(NOT_EQUAL)));
|
| + __ ret(0);
|
| +
|
| + // Check if the length is zero.
|
| + Label compare_chars;
|
| + __ bind(&check_zero_length);
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + __ test(length, Operand(length));
|
| + __ j(not_zero, &compare_chars, Label::kNear);
|
| + __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| + __ ret(0);
|
| +
|
| + // Compare characters.
|
| + __ bind(&compare_chars);
|
| + GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
|
| + &strings_not_equal, Label::kNear);
|
| +
|
| + // Characters are equal.
|
| + __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| + __ ret(0);
|
| +}
|
| +
|
| +
|
| void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
|
| Register left,
|
| Register right,
|
| Register scratch1,
|
| Register scratch2,
|
| Register scratch3) {
|
| - Label result_not_equal;
|
| - Label result_greater;
|
| - Label compare_lengths;
|
| -
|
| Counters* counters = masm->isolate()->counters();
|
| __ IncrementCounter(counters->string_compare_native(), 1);
|
|
|
| // Find minimum length.
|
| - NearLabel left_shorter;
|
| + Label left_shorter;
|
| __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
|
| __ mov(scratch3, scratch1);
|
| __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
|
|
|
| Register length_delta = scratch3;
|
|
|
| - __ j(less_equal, &left_shorter);
|
| + __ j(less_equal, &left_shorter, Label::kNear);
|
| // Right string is shorter. Change scratch1 to be length of right string.
|
| __ sub(scratch1, Operand(length_delta));
|
| __ bind(&left_shorter);
|
| @@ -5681,41 +5661,19 @@
|
| Register min_length = scratch1;
|
|
|
| // If either length is zero, just compare lengths.
|
| + Label compare_lengths;
|
| __ test(min_length, Operand(min_length));
|
| - __ j(zero, &compare_lengths);
|
| + __ j(zero, &compare_lengths, Label::kNear);
|
|
|
| - // Change index to run from -min_length to -1 by adding min_length
|
| - // to string start. This means that loop ends when index reaches zero,
|
| - // which doesn't need an additional compare.
|
| - __ SmiUntag(min_length);
|
| - __ lea(left,
|
| - FieldOperand(left,
|
| - min_length, times_1,
|
| - SeqAsciiString::kHeaderSize));
|
| - __ lea(right,
|
| - FieldOperand(right,
|
| - min_length, times_1,
|
| - SeqAsciiString::kHeaderSize));
|
| - __ neg(min_length);
|
| + // Compare characters.
|
| + Label result_not_equal;
|
| + GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
|
| + &result_not_equal, Label::kNear);
|
|
|
| - Register index = min_length; // index = -min_length;
|
| -
|
| - {
|
| - // Compare loop.
|
| - NearLabel loop;
|
| - __ bind(&loop);
|
| - // Compare characters.
|
| - __ mov_b(scratch2, Operand(left, index, times_1, 0));
|
| - __ cmpb(scratch2, Operand(right, index, times_1, 0));
|
| - __ j(not_equal, &result_not_equal);
|
| - __ add(Operand(index), Immediate(1));
|
| - __ j(not_zero, &loop);
|
| - }
|
| -
|
| // Compare lengths - strings up to min-length are equal.
|
| __ bind(&compare_lengths);
|
| __ test(length_delta, Operand(length_delta));
|
| - __ j(not_zero, &result_not_equal);
|
| + __ j(not_zero, &result_not_equal, Label::kNear);
|
|
|
| // Result is EQUAL.
|
| STATIC_ASSERT(EQUAL == 0);
|
| @@ -5723,8 +5681,9 @@
|
| __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| __ ret(0);
|
|
|
| + Label result_greater;
|
| __ bind(&result_not_equal);
|
| - __ j(greater, &result_greater);
|
| + __ j(greater, &result_greater, Label::kNear);
|
|
|
| // Result is LESS.
|
| __ Set(eax, Immediate(Smi::FromInt(LESS)));
|
| @@ -5737,6 +5696,36 @@
|
| }
|
|
|
|
|
| +void StringCompareStub::GenerateAsciiCharsCompareLoop(
|
| + MacroAssembler* masm,
|
| + Register left,
|
| + Register right,
|
| + Register length,
|
| + Register scratch,
|
| + Label* chars_not_equal,
|
| + Label::Distance chars_not_equal_near) {
|
| + // Change index to run from -length to -1 by adding length to string
|
| + // start. This means that loop ends when index reaches zero, which
|
| + // doesn't need an additional compare.
|
| + __ SmiUntag(length);
|
| + __ lea(left,
|
| + FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
|
| + __ lea(right,
|
| + FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
|
| + __ neg(length);
|
| + Register index = length; // index = -length;
|
| +
|
| + // Compare loop.
|
| + Label loop;
|
| + __ bind(&loop);
|
| + __ mov_b(scratch, Operand(left, index, times_1, 0));
|
| + __ cmpb(scratch, Operand(right, index, times_1, 0));
|
| + __ j(not_equal, chars_not_equal, chars_not_equal_near);
|
| + __ add(Operand(index), Immediate(1));
|
| + __ j(not_zero, &loop);
|
| +}
|
| +
|
| +
|
| void StringCompareStub::Generate(MacroAssembler* masm) {
|
| Label runtime;
|
|
|
| @@ -5748,9 +5737,9 @@
|
| __ mov(edx, Operand(esp, 2 * kPointerSize)); // left
|
| __ mov(eax, Operand(esp, 1 * kPointerSize)); // right
|
|
|
| - NearLabel not_same;
|
| + Label not_same;
|
| __ cmp(edx, Operand(eax));
|
| - __ j(not_equal, ¬_same);
|
| + __ j(not_equal, ¬_same, Label::kNear);
|
| STATIC_ASSERT(EQUAL == 0);
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| @@ -5778,19 +5767,19 @@
|
|
|
| void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
| ASSERT(state_ == CompareIC::SMIS);
|
| - NearLabel miss;
|
| + Label miss;
|
| __ mov(ecx, Operand(edx));
|
| __ or_(ecx, Operand(eax));
|
| __ test(ecx, Immediate(kSmiTagMask));
|
| - __ j(not_zero, &miss, not_taken);
|
| + __ j(not_zero, &miss, Label::kNear);
|
|
|
| if (GetCondition() == equal) {
|
| // For equality we do not care about the sign of the result.
|
| __ sub(eax, Operand(edx));
|
| } else {
|
| - NearLabel done;
|
| + Label done;
|
| __ sub(edx, Operand(eax));
|
| - __ j(no_overflow, &done);
|
| + __ j(no_overflow, &done, Label::kNear);
|
| // Correct sign of result in case of overflow.
|
| __ not_(edx);
|
| __ bind(&done);
|
| @@ -5806,18 +5795,18 @@
|
| void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
| ASSERT(state_ == CompareIC::HEAP_NUMBERS);
|
|
|
| - NearLabel generic_stub;
|
| - NearLabel unordered;
|
| - NearLabel miss;
|
| + Label generic_stub;
|
| + Label unordered;
|
| + Label miss;
|
| __ mov(ecx, Operand(edx));
|
| __ and_(ecx, Operand(eax));
|
| __ test(ecx, Immediate(kSmiTagMask));
|
| - __ j(zero, &generic_stub, not_taken);
|
| + __ j(zero, &generic_stub, Label::kNear);
|
|
|
| __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx);
|
| - __ j(not_equal, &miss, not_taken);
|
| + __ j(not_equal, &miss, Label::kNear);
|
| __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
|
| - __ j(not_equal, &miss, not_taken);
|
| + __ j(not_equal, &miss, Label::kNear);
|
|
|
| // Inlining the double comparison and falling back to the general compare
|
| // stub if NaN is involved or SS2 or CMOV is unsupported.
|
| @@ -5833,7 +5822,7 @@
|
| __ ucomisd(xmm0, xmm1);
|
|
|
| // Don't base result on EFLAGS when a NaN is involved.
|
| - __ j(parity_even, &unordered, not_taken);
|
| + __ j(parity_even, &unordered, Label::kNear);
|
|
|
| // Return a result of -1, 0, or 1, based on EFLAGS.
|
| // Performing mov, because xor would destroy the flag register.
|
| @@ -5856,8 +5845,55 @@
|
| }
|
|
|
|
|
| +void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
| + ASSERT(state_ == CompareIC::SYMBOLS);
|
| + ASSERT(GetCondition() == equal);
|
| +
|
| + // Registers containing left and right operands respectively.
|
| + Register left = edx;
|
| + Register right = eax;
|
| + Register tmp1 = ecx;
|
| + Register tmp2 = ebx;
|
| +
|
| + // Check that both operands are heap objects.
|
| + Label miss;
|
| + __ mov(tmp1, Operand(left));
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + __ and_(tmp1, Operand(right));
|
| + __ test(tmp1, Immediate(kSmiTagMask));
|
| + __ j(zero, &miss, Label::kNear);
|
| +
|
| + // Check that both operands are symbols.
|
| + __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
|
| + __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
|
| + __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
|
| + __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
|
| + STATIC_ASSERT(kSymbolTag != 0);
|
| + __ and_(tmp1, Operand(tmp2));
|
| + __ test(tmp1, Immediate(kIsSymbolMask));
|
| + __ j(zero, &miss, Label::kNear);
|
| +
|
| + // Symbols are compared by identity.
|
| + Label done;
|
| + __ cmp(left, Operand(right));
|
| + // Make sure eax is non-zero. At this point input operands are
|
| + // guaranteed to be non-zero.
|
| + ASSERT(right.is(eax));
|
| + __ j(not_equal, &done, Label::kNear);
|
| + STATIC_ASSERT(EQUAL == 0);
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| + __ bind(&done);
|
| + __ ret(0);
|
| +
|
| + __ bind(&miss);
|
| + GenerateMiss(masm);
|
| +}
|
| +
|
| +
|
| void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
| ASSERT(state_ == CompareIC::STRINGS);
|
| + ASSERT(GetCondition() == equal);
|
| Label miss;
|
|
|
| // Registers containing left and right operands respectively.
|
| @@ -5887,9 +5923,9 @@
|
| __ j(not_zero, &miss);
|
|
|
| // Fast check for identical strings.
|
| - NearLabel not_same;
|
| + Label not_same;
|
| __ cmp(left, Operand(right));
|
| - __ j(not_equal, ¬_same);
|
| + __ j(not_equal, ¬_same, Label::kNear);
|
| STATIC_ASSERT(EQUAL == 0);
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
|
| @@ -5900,12 +5936,11 @@
|
|
|
| // Check that both strings are symbols. If they are, we're done
|
| // because we already know they are not identical.
|
| - NearLabel do_compare;
|
| - ASSERT(GetCondition() == equal);
|
| + Label do_compare;
|
| STATIC_ASSERT(kSymbolTag != 0);
|
| __ and_(tmp1, Operand(tmp2));
|
| __ test(tmp1, Immediate(kIsSymbolMask));
|
| - __ j(zero, &do_compare);
|
| + __ j(zero, &do_compare, Label::kNear);
|
| // Make sure eax is non-zero. At this point input operands are
|
| // guaranteed to be non-zero.
|
| ASSERT(right.is(eax));
|
| @@ -5917,8 +5952,8 @@
|
| __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
|
|
|
| // Compare flat ASCII strings. Returns when done.
|
| - StringCompareStub::GenerateCompareFlatAsciiStrings(
|
| - masm, left, right, tmp1, tmp2, tmp3);
|
| + StringCompareStub::GenerateFlatAsciiStringEquals(
|
| + masm, left, right, tmp1, tmp2);
|
|
|
| // Handle more complex cases in runtime.
|
| __ bind(&runtime);
|
| @@ -5926,7 +5961,7 @@
|
| __ push(left);
|
| __ push(right);
|
| __ push(tmp1);
|
| - __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
|
| + __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
|
|
|
| __ bind(&miss);
|
| GenerateMiss(masm);
|
| @@ -5935,16 +5970,16 @@
|
|
|
| void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
|
| ASSERT(state_ == CompareIC::OBJECTS);
|
| - NearLabel miss;
|
| + Label miss;
|
| __ mov(ecx, Operand(edx));
|
| __ and_(ecx, Operand(eax));
|
| __ test(ecx, Immediate(kSmiTagMask));
|
| - __ j(zero, &miss, not_taken);
|
| + __ j(zero, &miss, Label::kNear);
|
|
|
| __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
|
| - __ j(not_equal, &miss, not_taken);
|
| + __ j(not_equal, &miss, Label::kNear);
|
| __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
|
| - __ j(not_equal, &miss, not_taken);
|
| + __ j(not_equal, &miss, Label::kNear);
|
|
|
| ASSERT(GetCondition() == equal);
|
| __ sub(eax, Operand(edx));
|
| @@ -5986,22 +6021,230 @@
|
| }
|
|
|
|
|
| +// Helper function used to check that the dictionary doesn't contain
|
| +// the property. This function may return false negatives, so miss_label
|
| +// must always call a backup property check that is complete.
|
| +// This function is safe to call if the receiver has fast properties.
|
| +// Name must be a symbol and receiver must be a heap object.
|
| +MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
|
| + MacroAssembler* masm,
|
| + Label* miss,
|
| + Label* done,
|
| + Register properties,
|
| + String* name,
|
| + Register r0) {
|
| + ASSERT(name->IsSymbol());
|
| +
|
| + // If names of slots in range from 1 to kProbes - 1 for the hash value are
|
| + // not equal to the name and kProbes-th slot is not used (its name is the
|
| + // undefined value), it guarantees the hash table doesn't contain the
|
| + // property. It's true even if some slots represent deleted properties
|
| + // (their names are the null value).
|
| + for (int i = 0; i < kInlinedProbes; i++) {
|
| + // Compute the masked index: (hash + i + i * i) & mask.
|
| + Register index = r0;
|
| + // Capacity is smi 2^n.
|
| + __ mov(index, FieldOperand(properties, kCapacityOffset));
|
| + __ dec(index);
|
| + __ and_(Operand(index),
|
| + Immediate(Smi::FromInt(name->Hash() +
|
| + StringDictionary::GetProbeOffset(i))));
|
| +
|
| + // Scale the index by multiplying by the entry size.
|
| + ASSERT(StringDictionary::kEntrySize == 3);
|
| + __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
|
| + Register entity_name = r0;
|
| + // Having undefined at this place means the name is not contained.
|
| + ASSERT_EQ(kSmiTagSize, 1);
|
| + __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
|
| + kElementsStartOffset - kHeapObjectTag));
|
| + __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
|
| + __ j(equal, done);
|
| +
|
| + // Stop if found the property.
|
| + __ cmp(entity_name, Handle<String>(name));
|
| + __ j(equal, miss);
|
| +
|
| + // Check if the entry name is not a symbol.
|
| + __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
|
| + __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
|
| + kIsSymbolMask);
|
| + __ j(zero, miss);
|
| + }
|
| +
|
| + StringDictionaryLookupStub stub(properties,
|
| + r0,
|
| + r0,
|
| + StringDictionaryLookupStub::NEGATIVE_LOOKUP);
|
| + __ push(Immediate(Handle<Object>(name)));
|
| + __ push(Immediate(name->Hash()));
|
| + MaybeObject* result = masm->TryCallStub(&stub);
|
| + if (result->IsFailure()) return result;
|
| + __ test(r0, Operand(r0));
|
| + __ j(not_zero, miss);
|
| + __ jmp(done);
|
| + return result;
|
| +}
|
| +
|
| +
|
| +// Probe the string dictionary in the |elements| register. Jump to the
|
| +// |done| label if a property with the given name is found leaving the
|
| +// index into the dictionary in |r0|. Jump to the |miss| label
|
| +// otherwise.
|
| +void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
|
| + Label* miss,
|
| + Label* done,
|
| + Register elements,
|
| + Register name,
|
| + Register r0,
|
| + Register r1) {
|
| + // Assert that name contains a string.
|
| + if (FLAG_debug_code) __ AbortIfNotString(name);
|
| +
|
| + __ mov(r1, FieldOperand(elements, kCapacityOffset));
|
| + __ shr(r1, kSmiTagSize); // convert smi to int
|
| + __ dec(r1);
|
| +
|
| + // Generate an unrolled loop that performs a few probes before
|
| + // giving up. Measurements done on Gmail indicate that 2 probes
|
| + // cover ~93% of loads from dictionaries.
|
| + for (int i = 0; i < kInlinedProbes; i++) {
|
| + // Compute the masked index: (hash + i + i * i) & mask.
|
| + __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
|
| + __ shr(r0, String::kHashShift);
|
| + if (i > 0) {
|
| + __ add(Operand(r0), Immediate(StringDictionary::GetProbeOffset(i)));
|
| + }
|
| + __ and_(r0, Operand(r1));
|
| +
|
| + // Scale the index by multiplying by the entry size.
|
| + ASSERT(StringDictionary::kEntrySize == 3);
|
| + __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3
|
| +
|
| + // Check if the key is identical to the name.
|
| + __ cmp(name, Operand(elements,
|
| + r0,
|
| + times_4,
|
| + kElementsStartOffset - kHeapObjectTag));
|
| + __ j(equal, done);
|
| + }
|
| +
|
| + StringDictionaryLookupStub stub(elements,
|
| + r1,
|
| + r0,
|
| + POSITIVE_LOOKUP);
|
| + __ push(name);
|
| + __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
|
| + __ shr(r0, String::kHashShift);
|
| + __ push(r0);
|
| + __ CallStub(&stub);
|
| +
|
| + __ test(r1, Operand(r1));
|
| + __ j(zero, miss);
|
| + __ jmp(done);
|
| +}
|
| +
|
| +
|
| +void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
|
| + // Stack frame on entry:
|
| + // esp[0 * kPointerSize]: return address.
|
| + // esp[1 * kPointerSize]: key's hash.
|
| + // esp[2 * kPointerSize]: key.
|
| + // Registers:
|
| + // dictionary_: StringDictionary to probe.
|
| + // result_: used as scratch.
|
| + // index_: will hold an index of entry if lookup is successful.
|
| + // might alias with result_.
|
| + // Returns:
|
| + // result_ is zero if lookup failed, non zero otherwise.
|
| +
|
| + Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
|
| +
|
| + Register scratch = result_;
|
| +
|
| + __ mov(scratch, FieldOperand(dictionary_, kCapacityOffset));
|
| + __ dec(scratch);
|
| + __ SmiUntag(scratch);
|
| + __ push(scratch);
|
| +
|
| + // If names of slots in range from 1 to kProbes - 1 for the hash value are
|
| + // not equal to the name and kProbes-th slot is not used (its name is the
|
| + // undefined value), it guarantees the hash table doesn't contain the
|
| + // property. It's true even if some slots represent deleted properties
|
| + // (their names are the null value).
|
| + for (int i = kInlinedProbes; i < kTotalProbes; i++) {
|
| + // Compute the masked index: (hash + i + i * i) & mask.
|
| + __ mov(scratch, Operand(esp, 2 * kPointerSize));
|
| + if (i > 0) {
|
| + __ add(Operand(scratch),
|
| + Immediate(StringDictionary::GetProbeOffset(i)));
|
| + }
|
| + __ and_(scratch, Operand(esp, 0));
|
| +
|
| + // Scale the index by multiplying by the entry size.
|
| + ASSERT(StringDictionary::kEntrySize == 3);
|
| + __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
|
| +
|
| + // Having undefined at this place means the name is not contained.
|
| + ASSERT_EQ(kSmiTagSize, 1);
|
| + __ mov(scratch, Operand(dictionary_,
|
| + index_,
|
| + times_pointer_size,
|
| + kElementsStartOffset - kHeapObjectTag));
|
| + __ cmp(scratch, masm->isolate()->factory()->undefined_value());
|
| + __ j(equal, ¬_in_dictionary);
|
| +
|
| + // Stop if found the property.
|
| + __ cmp(scratch, Operand(esp, 3 * kPointerSize));
|
| + __ j(equal, &in_dictionary);
|
| +
|
| + if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
|
| + // If we hit a non symbol key during negative lookup
|
| + // we have to bailout as this key might be equal to the
|
| + // key we are looking for.
|
| +
|
| + // Check if the entry name is not a symbol.
|
| + __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
|
| + __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset),
|
| + kIsSymbolMask);
|
| + __ j(zero, &maybe_in_dictionary);
|
| + }
|
| + }
|
| +
|
| + __ bind(&maybe_in_dictionary);
|
| + // If we are doing negative lookup then probing failure should be
|
| + // treated as a lookup success. For positive lookup probing failure
|
| + // should be treated as lookup failure.
|
| + if (mode_ == POSITIVE_LOOKUP) {
|
| + __ mov(result_, Immediate(0));
|
| + __ Drop(1);
|
| + __ ret(2 * kPointerSize);
|
| + }
|
| +
|
| + __ bind(&in_dictionary);
|
| + __ mov(result_, Immediate(1));
|
| + __ Drop(1);
|
| + __ ret(2 * kPointerSize);
|
| +
|
| + __ bind(¬_in_dictionary);
|
| + __ mov(result_, Immediate(0));
|
| + __ Drop(1);
|
| + __ ret(2 * kPointerSize);
|
| +}
|
| // Takes the input in 3 registers: address_ value_ and object_. A pointer to
|
| // the value has just been written into the object, now this stub makes sure
|
| // we keep the GC informed. The word in the object where the value has been
|
| // written is in the address register.
|
| void RecordWriteStub::Generate(MacroAssembler* masm) {
|
| - NearLabel skip_non_incremental_part;
|
| - __ jmp(&skip_non_incremental_part);
|
| + Label skip_non_incremental_part;
|
| + __ jmp(&skip_non_incremental_part, Label::kNear);
|
| if (!HEAP->incremental_marking()->IsMarking()) {
|
| ASSERT(masm->get_opcode(-2) == kSkipNonIncrementalPartInstruction);
|
| masm->set_opcode(-2, kTwoByteNopInstruction);
|
| }
|
|
|
| if (emit_remembered_set_ == EMIT_REMEMBERED_SET) {
|
| - NearLabel skip;
|
| __ RememberedSetHelper(address_, value_, save_fp_regs_mode_);
|
| - __ bind(&skip);
|
| }
|
| __ ret(0);
|
|
|
| @@ -6086,15 +6329,15 @@
|
| void RecordWriteStub::
|
| GenerateIncrementalValueIsInNewSpaceObjectIsInOldSpaceRememberedSet(
|
| MacroAssembler* masm) {
|
| - NearLabel object_is_black, must_inform_both;
|
| - Label must_inform_both_far;
|
| + Label object_is_black, must_inform_both, must_inform_both_far;
|
|
|
| // Lets look at the colour of the object: If it is not black we don't have to
|
| // inform the incremental marker.
|
| __ InOldSpaceIsBlack(regs_.object(),
|
| regs_.scratch0(),
|
| regs_.scratch1(),
|
| - &object_is_black);
|
| + &object_is_black,
|
| + Label::kNear);
|
| regs_.Restore(masm);
|
| __ RememberedSetHelper(address_, value_, save_fp_regs_mode_);
|
| __ ret(0);
|
| @@ -6108,6 +6351,7 @@
|
| regs_.scratch1(), // Scratch.
|
| regs_.object(), // Scratch.
|
| &must_inform_both,
|
| + Label::kNear,
|
| true); // In new space.
|
| __ pop(regs_.object());
|
| regs_.Restore(masm);
|
| @@ -6143,12 +6387,13 @@
|
| GenerateIncrementalValueIsInNewSpaceObjectIsInOldSpaceNoRememberedSet(
|
| MacroAssembler* masm,
|
| Label* value_in_new_space_object_is_black_no_remembered_set) {
|
| - NearLabel object_is_black, inform_incremental_marker;
|
| + Label object_is_black, inform_incremental_marker;
|
|
|
| __ InOldSpaceIsBlack(regs_.object(),
|
| regs_.scratch0(),
|
| regs_.scratch1(),
|
| - &object_is_black);
|
| + &object_is_black,
|
| + Label::kNear);
|
| regs_.Restore(masm);
|
| __ ret(0);
|
|
|
| @@ -6166,6 +6411,7 @@
|
| regs_.scratch1(), // Scratch.
|
| regs_.object(), // Scratch.
|
| &inform_incremental_marker,
|
| + Label::kNear,
|
| true); // In new space.
|
| __ pop(regs_.object());
|
| regs_.Restore(masm);
|
| @@ -6180,8 +6426,7 @@
|
|
|
| void RecordWriteStub::GenerateIncrementalValueIsInOldSpace(
|
| MacroAssembler* masm) {
|
| - NearLabel value_is_white;
|
| - Label value_in_old_space_and_white_object_in_new_space;
|
| + Label value_is_white, value_in_old_space_and_white_object_in_new_space;
|
| // If the value is in old space then the remembered set doesn't care. We may
|
| // be able to avoid logging anything if the incremental marker doesn't care
|
| // either.
|
| @@ -6191,6 +6436,7 @@
|
| regs_.scratch1(), // Scratch.
|
| regs_.object(), // Scratch.
|
| &value_is_white,
|
| + Label::kNear,
|
| false); // In old space.
|
| __ pop(regs_.object());
|
| regs_.Restore(masm);
|
|
|