| Index: src/ia32/macro-assembler-ia32.cc
|
| ===================================================================
|
| --- src/ia32/macro-assembler-ia32.cc (revision 7948)
|
| +++ src/ia32/macro-assembler-ia32.cc (working copy)
|
| @@ -94,7 +94,7 @@
|
| void MacroAssembler::RememberedSetHelper(Register addr,
|
| Register scratch,
|
| SaveFPRegsMode save_fp) {
|
| - NearLabel done;
|
| + Label done;
|
| // Load store buffer top.
|
| ExternalReference store_buffer =
|
| ExternalReference::store_buffer_top(isolate());
|
| @@ -108,7 +108,7 @@
|
| // Call stub on end of buffer.
|
| // Check for end of buffer.
|
| test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
|
| - j(equal, &done);
|
| + j(equal, &done, Label::kNear);
|
| StoreBufferOverflowStub store_buffer_overflow =
|
| StoreBufferOverflowStub(save_fp);
|
| CallStub(&store_buffer_overflow);
|
| @@ -116,6 +116,63 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
|
| + XMMRegister scratch_reg,
|
| + Register result_reg) {
|
| + Label done;
|
| + ExternalReference zero_ref = ExternalReference::address_of_zero();
|
| + movdbl(scratch_reg, Operand::StaticVariable(zero_ref));
|
| + Set(result_reg, Immediate(0));
|
| + ucomisd(input_reg, scratch_reg);
|
| + j(below, &done, Label::kNear);
|
| + ExternalReference half_ref = ExternalReference::address_of_one_half();
|
| + movdbl(scratch_reg, Operand::StaticVariable(half_ref));
|
| + addsd(scratch_reg, input_reg);
|
| + cvttsd2si(result_reg, Operand(scratch_reg));
|
| + test(result_reg, Immediate(0xFFFFFF00));
|
| + j(zero, &done, Label::kNear);
|
| + Set(result_reg, Immediate(255));
|
| + bind(&done);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::ClampUint8(Register reg) {
|
| + Label done;
|
| + test(reg, Immediate(0xFFFFFF00));
|
| + j(zero, &done, Label::kNear);
|
| + setcc(negative, reg); // 1 if negative, 0 if positive.
|
| + dec_b(reg); // 0 if negative, 255 if positive.
|
| + bind(&done);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::InNewSpace(Register object,
|
| + Register scratch,
|
| + Condition cc,
|
| + Label* branch,
|
| + Label::Distance branch_near) {
|
| + ASSERT(cc == equal || cc == not_equal);
|
| + if (Serializer::enabled()) {
|
| + // Can't do arithmetic on external references if it might get serialized.
|
| + mov(scratch, Operand(object));
|
| + // The mask isn't really an address. We load it as an external reference in
|
| + // case the size of the new space is different between the snapshot maker
|
| + // and the running system.
|
| + and_(Operand(scratch),
|
| + Immediate(ExternalReference::new_space_mask(isolate())));
|
| + cmp(Operand(scratch),
|
| + Immediate(ExternalReference::new_space_start(isolate())));
|
| + j(cc, branch, branch_near);
|
| + } else {
|
| + int32_t new_space_start = reinterpret_cast<int32_t>(
|
| + ExternalReference::new_space_start(isolate()).address());
|
| + lea(scratch, Operand(object, -new_space_start));
|
| + and_(scratch, isolate()->heap()->NewSpaceMask());
|
| + j(cc, branch, branch_near);
|
| + }
|
| +}
|
| +
|
| +
|
| void MacroAssembler::RecordWriteArray(Register object,
|
| Register value,
|
| Register index,
|
| @@ -124,7 +181,7 @@
|
| SmiCheck smi_check) {
|
| // First, check if a write barrier is even needed. The tests below
|
| // catch stores of Smis.
|
| - NearLabel done;
|
| + Label done;
|
|
|
| // Skip barrier if writing a smi.
|
| if (smi_check == INLINE_SMI_CHECK) {
|
| @@ -138,6 +195,8 @@
|
| // into an array of words.
|
| ASSERT_EQ(1, kSmiTagSize);
|
| ASSERT_EQ(0, kSmiTag);
|
| + test(value, Immediate(kSmiTagMask));
|
| + j(zero, &done, Label::kNear);
|
| Register dst = index;
|
| lea(dst, Operand(object, index, times_half_pointer_size,
|
| FixedArray::kHeaderSize - kHeapObjectTag));
|
| @@ -165,13 +224,13 @@
|
| SmiCheck smi_check) {
|
| // First, check if a write barrier is even needed. The tests below
|
| // catch stores of Smis.
|
| - NearLabel done;
|
| + Label done;
|
|
|
| // Skip barrier if writing a smi.
|
| if (smi_check == INLINE_SMI_CHECK) {
|
| ASSERT_EQ(0, kSmiTag);
|
| test(value, Immediate(kSmiTagMask));
|
| - j(zero, &done);
|
| + j(zero, &done, Label::kNear);
|
| }
|
|
|
| // Although the object register is tagged, the offset is relative to the start
|
| @@ -180,9 +239,9 @@
|
|
|
| lea(dst, FieldOperand(object, offset));
|
| if (emit_debug_code()) {
|
| - NearLabel ok;
|
| + Label ok;
|
| test_b(Operand(dst), (1 << kPointerSizeLog2) - 1);
|
| - j(zero, &ok);
|
| + j(zero, &ok, Label::kNear);
|
| int3();
|
| bind(&ok);
|
| }
|
| @@ -219,34 +278,36 @@
|
| }
|
|
|
| if (FLAG_debug_code) {
|
| - NearLabel ok;
|
| + Label ok;
|
| cmp(value, Operand(address, 0));
|
| - j(equal, &ok);
|
| - Abort("Registers did not match in write barrier");
|
| + j(equal, &ok, Label::kNear);
|
| + int3();
|
| bind(&ok);
|
| }
|
|
|
| // First, check if a write barrier is even needed. The tests below
|
| // catch stores of Smis and stores into young gen.
|
| - NearLabel done;
|
| + Label done;
|
|
|
| if (smi_check == INLINE_SMI_CHECK) {
|
| // Skip barrier if writing a smi.
|
| ASSERT_EQ(0, kSmiTag);
|
| test(value, Immediate(kSmiTagMask));
|
| - j(zero, &done);
|
| + j(zero, &done, Label::kNear);
|
| }
|
|
|
| CheckPageFlag(value,
|
| value, // Used as scratch.
|
| MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING,
|
| zero,
|
| - &done);
|
| + &done,
|
| + Label::kNear);
|
| CheckPageFlag(object,
|
| value, // Used as scratch.
|
| MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING,
|
| zero,
|
| - &done);
|
| + &done,
|
| + Label::kNear);
|
|
|
| RecordWriteStub stub(object, value, address, emit_remembered_set, fp_mode);
|
| CallStub(&stub);
|
| @@ -274,7 +335,7 @@
|
|
|
| void MacroAssembler::Set(Register dst, const Immediate& x) {
|
| if (x.is_zero()) {
|
| - xor_(dst, Operand(dst)); // shorter than mov
|
| + xor_(dst, Operand(dst)); // Shorter than mov.
|
| } else {
|
| mov(dst, x);
|
| }
|
| @@ -286,6 +347,33 @@
|
| }
|
|
|
|
|
| +bool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
|
| + static const int kMaxImmediateBits = 17;
|
| + if (x.rmode_ != RelocInfo::NONE) return false;
|
| + return !is_intn(x.x_, kMaxImmediateBits);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::SafeSet(Register dst, const Immediate& x) {
|
| + if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
|
| + Set(dst, Immediate(x.x_ ^ jit_cookie()));
|
| + xor_(dst, jit_cookie());
|
| + } else {
|
| + Set(dst, x);
|
| + }
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::SafePush(const Immediate& x) {
|
| + if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
|
| + push(Immediate(x.x_ ^ jit_cookie()));
|
| + xor_(Operand(esp, 0), Immediate(jit_cookie()));
|
| + } else {
|
| + push(x);
|
| + }
|
| +}
|
| +
|
| +
|
| void MacroAssembler::CmpObjectType(Register heap_object,
|
| InstanceType type,
|
| Register map) {
|
| @@ -303,16 +391,30 @@
|
| void MacroAssembler::CheckMap(Register obj,
|
| Handle<Map> map,
|
| Label* fail,
|
| - bool is_heap_object) {
|
| - if (!is_heap_object) {
|
| - test(obj, Immediate(kSmiTagMask));
|
| - j(zero, fail);
|
| + SmiCheckType smi_check_type) {
|
| + if (smi_check_type == DONT_DO_SMI_CHECK) {
|
| + JumpIfSmi(obj, fail);
|
| }
|
| cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
|
| j(not_equal, fail);
|
| }
|
|
|
|
|
| +void MacroAssembler::DispatchMap(Register obj,
|
| + Handle<Map> map,
|
| + Handle<Code> success,
|
| + SmiCheckType smi_check_type) {
|
| + Label fail;
|
| + if (smi_check_type == DONT_DO_SMI_CHECK) {
|
| + JumpIfSmi(obj, &fail);
|
| + }
|
| + cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
|
| + j(equal, success);
|
| +
|
| + bind(&fail);
|
| +}
|
| +
|
| +
|
| Condition MacroAssembler::IsObjectStringType(Register heap_object,
|
| Register map,
|
| Register instance_type) {
|
| @@ -594,9 +696,9 @@
|
| // not NULL. The frame pointer is NULL in the exception handler of
|
| // a JS entry frame.
|
| Set(esi, Immediate(0)); // Tentatively set context pointer to NULL.
|
| - NearLabel skip;
|
| + Label skip;
|
| cmp(ebp, 0);
|
| - j(equal, &skip, not_taken);
|
| + j(equal, &skip, Label::kNear);
|
| mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| bind(&skip);
|
|
|
| @@ -621,12 +723,12 @@
|
| mov(esp, Operand::StaticVariable(handler_address));
|
|
|
| // Unwind the handlers until the ENTRY handler is found.
|
| - NearLabel loop, done;
|
| + Label loop, done;
|
| bind(&loop);
|
| // Load the type of the current stack handler.
|
| const int kStateOffset = StackHandlerConstants::kStateOffset;
|
| cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
|
| - j(equal, &done);
|
| + j(equal, &done, Label::kNear);
|
| // Fetch the next handler in the list.
|
| const int kNextOffset = StackHandlerConstants::kNextOffset;
|
| mov(esp, Operand(esp, kNextOffset));
|
| @@ -697,7 +799,7 @@
|
|
|
| // Check if both contexts are the same.
|
| cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
|
| - j(equal, &same_contexts, taken);
|
| + j(equal, &same_contexts);
|
|
|
| // Compare security tokens, save holder_reg on the stack so we can use it
|
| // as a temporary register.
|
| @@ -727,7 +829,7 @@
|
| mov(scratch, FieldOperand(scratch, token_offset));
|
| cmp(scratch, FieldOperand(holder_reg, token_offset));
|
| pop(holder_reg);
|
| - j(not_equal, miss, not_taken);
|
| + j(not_equal, miss);
|
|
|
| bind(&same_contexts);
|
| }
|
| @@ -815,9 +917,9 @@
|
| mov(top_reg, result);
|
| }
|
| add(Operand(top_reg), Immediate(object_size));
|
| - j(carry, gc_required, not_taken);
|
| + j(carry, gc_required);
|
| cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
|
| - j(above, gc_required, not_taken);
|
| + j(above, gc_required);
|
|
|
| // Update allocation top.
|
| UpdateAllocationTopHelper(top_reg, scratch);
|
| @@ -914,9 +1016,9 @@
|
| mov(result_end, object_size);
|
| }
|
| add(result_end, Operand(result));
|
| - j(carry, gc_required, not_taken);
|
| + j(carry, gc_required);
|
| cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
|
| - j(above, gc_required, not_taken);
|
| + j(above, gc_required);
|
|
|
| // Tag result if requested.
|
| if ((flags & TAG_OBJECT) != 0) {
|
| @@ -1145,9 +1247,9 @@
|
| Label* then_label) {
|
| Label ok;
|
| test(result, Operand(result));
|
| - j(not_zero, &ok, taken);
|
| + j(not_zero, &ok);
|
| test(op, Operand(op));
|
| - j(sign, then_label, not_taken);
|
| + j(sign, then_label);
|
| bind(&ok);
|
| }
|
|
|
| @@ -1159,10 +1261,10 @@
|
| Label* then_label) {
|
| Label ok;
|
| test(result, Operand(result));
|
| - j(not_zero, &ok, taken);
|
| + j(not_zero, &ok);
|
| mov(scratch, Operand(op1));
|
| or_(scratch, Operand(op2));
|
| - j(sign, then_label, not_taken);
|
| + j(sign, then_label);
|
| bind(&ok);
|
| }
|
|
|
| @@ -1173,17 +1275,17 @@
|
| Label* miss) {
|
| // Check that the receiver isn't a smi.
|
| test(function, Immediate(kSmiTagMask));
|
| - j(zero, miss, not_taken);
|
| + j(zero, miss);
|
|
|
| // Check that the function really is a function.
|
| CmpObjectType(function, JS_FUNCTION_TYPE, result);
|
| - j(not_equal, miss, not_taken);
|
| + j(not_equal, miss);
|
|
|
| // Make sure that the function has an instance prototype.
|
| Label non_instance;
|
| movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
|
| test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
|
| - j(not_zero, &non_instance, not_taken);
|
| + j(not_zero, &non_instance);
|
|
|
| // Get the prototype or initial map from the function.
|
| mov(result,
|
| @@ -1193,7 +1295,7 @@
|
| // simply miss the cache instead. This will allow us to allocate a
|
| // prototype object on-demand in the runtime system.
|
| cmp(Operand(result), Immediate(isolate()->factory()->the_hole_value()));
|
| - j(equal, miss, not_taken);
|
| + j(equal, miss);
|
|
|
| // If the function does not have an initial map, we're done.
|
| Label done;
|
| @@ -1215,7 +1317,8 @@
|
|
|
|
|
| void MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) {
|
| - ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
|
| + // ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
|
| + // TODO(gc): Fix this!
|
| call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
|
| }
|
|
|
| @@ -1473,7 +1576,7 @@
|
|
|
| // Check if the result handle holds 0.
|
| test(eax, Operand(eax));
|
| - j(zero, &empty_handle, not_taken);
|
| + j(zero, &empty_handle);
|
| // It was non-zero. Dereference to get the result value.
|
| mov(eax, Operand(eax, 0));
|
| bind(&prologue);
|
| @@ -1483,7 +1586,7 @@
|
| sub(Operand::StaticVariable(level_address), Immediate(1));
|
| Assert(above_equal, "Invalid HandleScope level");
|
| cmp(edi, Operand::StaticVariable(limit_address));
|
| - j(not_equal, &delete_allocated_handles, not_taken);
|
| + j(not_equal, &delete_allocated_handles);
|
| bind(&leave_exit_frame);
|
|
|
| // Check if the function scheduled an exception.
|
| @@ -1491,7 +1594,7 @@
|
| ExternalReference::scheduled_exception_address(isolate());
|
| cmp(Operand::StaticVariable(scheduled_exception_address),
|
| Immediate(isolate()->factory()->the_hole_value()));
|
| - j(not_equal, &promote_scheduled_exception, not_taken);
|
| + j(not_equal, &promote_scheduled_exception);
|
| LeaveApiExitFrame();
|
| ret(stack_space * kPointerSize);
|
| bind(&promote_scheduled_exception);
|
| @@ -1542,8 +1645,9 @@
|
| const ParameterCount& actual,
|
| Handle<Code> code_constant,
|
| const Operand& code_operand,
|
| - NearLabel* done,
|
| + Label* done,
|
| InvokeFlag flag,
|
| + Label::Distance done_near,
|
| const CallWrapper& call_wrapper) {
|
| bool definitely_matches = false;
|
| Label invoke;
|
| @@ -1597,7 +1701,7 @@
|
| call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
|
| call(adaptor, RelocInfo::CODE_TARGET);
|
| call_wrapper.AfterCall();
|
| - jmp(done);
|
| + jmp(done, done_near);
|
| } else {
|
| jmp(adaptor, RelocInfo::CODE_TARGET);
|
| }
|
| @@ -1611,9 +1715,9 @@
|
| const ParameterCount& actual,
|
| InvokeFlag flag,
|
| const CallWrapper& call_wrapper) {
|
| - NearLabel done;
|
| + Label done;
|
| InvokePrologue(expected, actual, Handle<Code>::null(), code,
|
| - &done, flag, call_wrapper);
|
| + &done, flag, Label::kNear, call_wrapper);
|
| if (flag == CALL_FUNCTION) {
|
| call_wrapper.BeforeCall(CallSize(code));
|
| call(code);
|
| @@ -1632,9 +1736,10 @@
|
| RelocInfo::Mode rmode,
|
| InvokeFlag flag,
|
| const CallWrapper& call_wrapper) {
|
| - NearLabel done;
|
| + Label done;
|
| Operand dummy(eax);
|
| - InvokePrologue(expected, actual, code, dummy, &done, flag, call_wrapper);
|
| + InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear,
|
| + call_wrapper);
|
| if (flag == CALL_FUNCTION) {
|
| call_wrapper.BeforeCall(CallSize(code, rmode));
|
| call(code, rmode);
|
| @@ -1765,7 +1870,7 @@
|
| mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
|
| if (emit_debug_code()) {
|
| Label ok, fail;
|
| - CheckMap(map, isolate()->factory()->meta_map(), &fail, false);
|
| + CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
|
| jmp(&ok);
|
| bind(&fail);
|
| Abort("Global functions must have initial map");
|
| @@ -1929,7 +2034,7 @@
|
|
|
| void MacroAssembler::Check(Condition cc, const char* msg) {
|
| Label L;
|
| - j(cc, &L, taken);
|
| + j(cc, &L);
|
| Abort(msg);
|
| // will not return here
|
| bind(&L);
|
| @@ -1978,59 +2083,6 @@
|
| }
|
|
|
|
|
| -void MacroAssembler::JumpIfNotNumber(Register reg,
|
| - TypeInfo info,
|
| - Label* on_not_number) {
|
| - if (emit_debug_code()) AbortIfSmi(reg);
|
| - if (!info.IsNumber()) {
|
| - cmp(FieldOperand(reg, HeapObject::kMapOffset),
|
| - isolate()->factory()->heap_number_map());
|
| - j(not_equal, on_not_number);
|
| - }
|
| -}
|
| -
|
| -
|
| -void MacroAssembler::ConvertToInt32(Register dst,
|
| - Register source,
|
| - Register scratch,
|
| - TypeInfo info,
|
| - Label* on_not_int32) {
|
| - if (emit_debug_code()) {
|
| - AbortIfSmi(source);
|
| - AbortIfNotNumber(source);
|
| - }
|
| - if (info.IsInteger32()) {
|
| - cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset));
|
| - } else {
|
| - Label done;
|
| - bool push_pop = (scratch.is(no_reg) && dst.is(source));
|
| - ASSERT(!scratch.is(source));
|
| - if (push_pop) {
|
| - push(dst);
|
| - scratch = dst;
|
| - }
|
| - if (scratch.is(no_reg)) scratch = dst;
|
| - cvttsd2si(scratch, FieldOperand(source, HeapNumber::kValueOffset));
|
| - cmp(scratch, 0x80000000u);
|
| - if (push_pop) {
|
| - j(not_equal, &done);
|
| - pop(dst);
|
| - jmp(on_not_int32);
|
| - } else {
|
| - j(equal, on_not_int32);
|
| - }
|
| -
|
| - bind(&done);
|
| - if (push_pop) {
|
| - add(Operand(esp), Immediate(kPointerSize)); // Pop.
|
| - }
|
| - if (!scratch.is(dst)) {
|
| - mov(dst, scratch);
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| void MacroAssembler::LoadPowerOf2(XMMRegister dst,
|
| Register scratch,
|
| int power) {
|
|
|