Merge Label and NearLabel
by adding NearLabel's functionality to Label and introducing a "near" parameter to jump instructions. TEST=compiles; existing tests still pass. Review URL: http://codereview.chromium.org/6928060 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7832 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5d8cd989ab
commit
95ff85112f
@ -78,18 +78,28 @@ class DoubleConstant: public AllStatic {
|
||||
|
||||
class Label BASE_EMBEDDED {
|
||||
public:
|
||||
INLINE(Label()) { Unuse(); }
|
||||
enum Distance {
|
||||
kNear, kFar
|
||||
};
|
||||
|
||||
INLINE(Label()) {
|
||||
Unuse();
|
||||
UnuseNear();
|
||||
}
|
||||
INLINE(~Label()) { ASSERT(!is_linked()); }
|
||||
|
||||
INLINE(void Unuse()) { pos_ = 0; }
|
||||
INLINE(void UnuseNear()) { near_link_pos_ = 0; }
|
||||
|
||||
INLINE(bool is_bound() const) { return pos_ < 0; }
|
||||
INLINE(bool is_unused() const) { return pos_ == 0; }
|
||||
INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
|
||||
INLINE(bool is_linked() const) { return pos_ > 0; }
|
||||
INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
|
||||
|
||||
// Returns the position of bound or linked labels. Cannot be used
|
||||
// for unused labels.
|
||||
int pos() const;
|
||||
int near_link_pos() const { return near_link_pos_ - 1; }
|
||||
|
||||
private:
|
||||
// pos_ encodes both the binding state (via its sign)
|
||||
@ -100,13 +110,21 @@ class Label BASE_EMBEDDED {
|
||||
// pos_ > 0 linked label, pos() returns the last reference position
|
||||
int pos_;
|
||||
|
||||
// Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
|
||||
int near_link_pos_;
|
||||
|
||||
void bind_to(int pos) {
|
||||
pos_ = -pos - 1;
|
||||
ASSERT(is_bound());
|
||||
}
|
||||
void link_to(int pos) {
|
||||
pos_ = pos + 1;
|
||||
ASSERT(is_linked());
|
||||
void link_to(int pos, Distance distance = kFar) {
|
||||
if (distance == kNear) {
|
||||
near_link_pos_ = pos + 1;
|
||||
ASSERT(is_near_linked());
|
||||
} else {
|
||||
pos_ = pos + 1;
|
||||
ASSERT(is_linked());
|
||||
}
|
||||
}
|
||||
|
||||
friend class Assembler;
|
||||
|
@ -380,6 +380,18 @@ void Assembler::emit_disp(Label* L, Displacement::Type type) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::emit_near_disp(Label* L) {
|
||||
byte disp = 0x00;
|
||||
if (L->is_near_linked()) {
|
||||
int offset = L->near_link_pos() - pc_offset();
|
||||
ASSERT(is_int8(offset));
|
||||
disp = static_cast<byte>(offset & 0xFF);
|
||||
}
|
||||
L->link_to(pc_offset(), Label::kNear);
|
||||
*pc_++ = disp;
|
||||
}
|
||||
|
||||
|
||||
void Operand::set_modrm(int mod, Register rm) {
|
||||
ASSERT((mod & -4) == 0);
|
||||
buf_[0] = mod << 6 | rm.code();
|
||||
|
@ -1525,6 +1525,21 @@ void Assembler::bind_to(Label* L, int pos) {
|
||||
}
|
||||
disp.next(L);
|
||||
}
|
||||
while (L->is_near_linked()) {
|
||||
int fixup_pos = L->near_link_pos();
|
||||
int offset_to_next =
|
||||
static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
|
||||
ASSERT(offset_to_next <= 0);
|
||||
// Relative address, relative to point after address.
|
||||
int disp = pos - fixup_pos - sizeof(int8_t);
|
||||
ASSERT(0 <= disp && disp <= 127);
|
||||
set_byte_at(fixup_pos, disp);
|
||||
if (offset_to_next < 0) {
|
||||
L->link_to(fixup_pos + offset_to_next, Label::kNear);
|
||||
} else {
|
||||
L->UnuseNear();
|
||||
}
|
||||
}
|
||||
L->bind_to(pos);
|
||||
}
|
||||
|
||||
@ -1613,7 +1628,7 @@ void Assembler::call(Handle<Code> code,
|
||||
}
|
||||
|
||||
|
||||
void Assembler::jmp(Label* L) {
|
||||
void Assembler::jmp(Label* L, Label::Distance distance) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
if (L->is_bound()) {
|
||||
@ -1630,6 +1645,9 @@ void Assembler::jmp(Label* L) {
|
||||
EMIT(0xE9);
|
||||
emit(offs - long_size);
|
||||
}
|
||||
} else if (distance == Label::kNear) {
|
||||
EMIT(0xEB);
|
||||
emit_near_disp(L);
|
||||
} else {
|
||||
// 1110 1001 #32-bit disp.
|
||||
EMIT(0xE9);
|
||||
@ -1683,7 +1701,7 @@ void Assembler::jmp(NearLabel* L) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::j(Condition cc, Label* L, Hint hint) {
|
||||
void Assembler::j(Condition cc, Label* L, Hint hint, Label::Distance distance) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
ASSERT(0 <= cc && cc < 16);
|
||||
@ -1703,6 +1721,9 @@ void Assembler::j(Condition cc, Label* L, Hint hint) {
|
||||
EMIT(0x80 | cc);
|
||||
emit(offs - long_size);
|
||||
}
|
||||
} else if (distance == Label::kNear) {
|
||||
EMIT(0x70 | cc);
|
||||
emit_near_disp(L);
|
||||
} else {
|
||||
// 0000 1111 1000 tttn #32-bit disp
|
||||
// Note: could eliminate cond. jumps to this jump if condition
|
||||
|
@ -842,6 +842,7 @@ class Assembler : public AssemblerBase {
|
||||
// but it may be bound only once.
|
||||
|
||||
void bind(Label* L); // binds an unbound label L to the current code position
|
||||
// DEPRECATED. Use bind(Label*) with jmp(Label*, Label::kNear) instead.
|
||||
void bind(NearLabel* L);
|
||||
|
||||
// Calls
|
||||
@ -855,20 +856,29 @@ class Assembler : public AssemblerBase {
|
||||
unsigned ast_id = kNoASTId);
|
||||
|
||||
// Jumps
|
||||
void jmp(Label* L); // unconditional jump to L
|
||||
// unconditional jump to L
|
||||
void jmp(Label* L, Label::Distance distance = Label::kFar);
|
||||
void jmp(byte* entry, RelocInfo::Mode rmode);
|
||||
void jmp(const Operand& adr);
|
||||
void jmp(Handle<Code> code, RelocInfo::Mode rmode);
|
||||
|
||||
// Short jump
|
||||
// DEPRECATED. Use jmp(Label*, Label::kNear) instead.
|
||||
void jmp(NearLabel* L);
|
||||
|
||||
// Conditional jumps
|
||||
void j(Condition cc, Label* L, Hint hint = no_hint);
|
||||
void j(Condition cc,
|
||||
Label* L,
|
||||
Hint hint,
|
||||
Label::Distance distance = Label::kFar);
|
||||
void j(Condition cc, Label* L, Label::Distance distance = Label::kFar) {
|
||||
j(cc, L, no_hint, distance);
|
||||
}
|
||||
void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
|
||||
void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
|
||||
|
||||
// Conditional short jump
|
||||
// DEPRECATED. Use j(Condition, Label*, Label::kNear) instead.
|
||||
void j(Condition cc, NearLabel* L, Hint hint = no_hint);
|
||||
|
||||
// Floating-point operations
|
||||
@ -1105,6 +1115,7 @@ class Assembler : public AssemblerBase {
|
||||
inline Displacement disp_at(Label* L);
|
||||
inline void disp_at_put(Label* L, Displacement disp);
|
||||
inline void emit_disp(Label* L, Displacement::Type type);
|
||||
inline void emit_near_disp(Label* L);
|
||||
|
||||
// record reloc info for current pc_
|
||||
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
|
||||
|
@ -520,15 +520,15 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
|
||||
__ SmiUntag(ecx);
|
||||
|
||||
// Switch on the state.
|
||||
NearLabel not_no_registers, not_tos_eax;
|
||||
Label not_no_registers, not_tos_eax;
|
||||
__ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
|
||||
__ j(not_equal, ¬_no_registers);
|
||||
__ j(not_equal, ¬_no_registers, Label::kNear);
|
||||
__ ret(1 * kPointerSize); // Remove state.
|
||||
|
||||
__ bind(¬_no_registers);
|
||||
__ mov(eax, Operand(esp, 2 * kPointerSize));
|
||||
__ cmp(ecx, FullCodeGenerator::TOS_REG);
|
||||
__ j(not_equal, ¬_tos_eax);
|
||||
__ j(not_equal, ¬_tos_eax, Label::kNear);
|
||||
__ ret(2 * kPointerSize); // Remove state, eax.
|
||||
|
||||
__ bind(¬_tos_eax);
|
||||
@ -1577,19 +1577,19 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
|
||||
|
||||
// If the result was -1 it means that we couldn't optimize the
|
||||
// function. Just return and continue in the unoptimized version.
|
||||
NearLabel skip;
|
||||
Label skip;
|
||||
__ cmp(Operand(eax), Immediate(Smi::FromInt(-1)));
|
||||
__ j(not_equal, &skip);
|
||||
__ j(not_equal, &skip, Label::kNear);
|
||||
__ ret(0);
|
||||
|
||||
// If we decide not to perform on-stack replacement we perform a
|
||||
// stack guard check to enable interrupts.
|
||||
__ bind(&stack_check);
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
ExternalReference stack_limit =
|
||||
ExternalReference::address_of_stack_limit(masm->isolate());
|
||||
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
||||
__ j(above_equal, &ok, taken);
|
||||
__ j(above_equal, &ok, taken, Label::kNear);
|
||||
StackCheckStub stub;
|
||||
__ TailCallStub(&stub);
|
||||
__ Abort("Unreachable code: returned from tail call.");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -237,11 +237,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
|
||||
|
||||
{ Comment cmnt(masm_, "[ Stack check");
|
||||
PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
ExternalReference stack_limit =
|
||||
ExternalReference::address_of_stack_limit(isolate());
|
||||
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
||||
__ j(above_equal, &ok, taken);
|
||||
__ j(above_equal, &ok, taken, Label::kNear);
|
||||
StackCheckStub stub;
|
||||
__ CallStub(&stub);
|
||||
__ bind(&ok);
|
||||
@ -270,11 +270,11 @@ void FullCodeGenerator::ClearAccumulator() {
|
||||
|
||||
void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ Stack check");
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
ExternalReference stack_limit =
|
||||
ExternalReference::address_of_stack_limit(isolate());
|
||||
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
||||
__ j(above_equal, &ok, taken);
|
||||
__ j(above_equal, &ok, taken, Label::kNear);
|
||||
StackCheckStub stub;
|
||||
__ CallStub(&stub);
|
||||
// Record a mapping of this PC offset to the OSR id. This is used to find
|
||||
@ -471,10 +471,10 @@ void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
|
||||
void FullCodeGenerator::AccumulatorValueContext::Plug(
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) const {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ bind(materialize_true);
|
||||
__ mov(result_register(), isolate()->factory()->true_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(materialize_false);
|
||||
__ mov(result_register(), isolate()->factory()->false_value());
|
||||
__ bind(&done);
|
||||
@ -484,10 +484,10 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(
|
||||
void FullCodeGenerator::StackValueContext::Plug(
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) const {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ bind(materialize_true);
|
||||
__ push(Immediate(isolate()->factory()->true_value()));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(materialize_false);
|
||||
__ push(Immediate(isolate()->factory()->false_value()));
|
||||
__ bind(&done);
|
||||
@ -627,8 +627,8 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
||||
// preparation to avoid preparing with the same AST id twice.
|
||||
if (!context()->IsTest() || !info_->IsOptimizable()) return;
|
||||
|
||||
NearLabel skip;
|
||||
if (should_normalize) __ jmp(&skip);
|
||||
Label skip;
|
||||
if (should_normalize) __ jmp(&skip, Label::kNear);
|
||||
|
||||
ForwardBailoutStack* current = forward_bailout_stack_;
|
||||
while (current != NULL) {
|
||||
@ -862,11 +862,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ j(equal, &exit);
|
||||
|
||||
// Convert the object to a JS object.
|
||||
NearLabel convert, done_convert;
|
||||
Label convert, done_convert;
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &convert);
|
||||
__ j(zero, &convert, Label::kNear);
|
||||
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
||||
__ j(above_equal, &done_convert);
|
||||
__ j(above_equal, &done_convert, Label::kNear);
|
||||
__ bind(&convert);
|
||||
__ push(eax);
|
||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
||||
@ -903,9 +903,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ j(zero, &call_runtime);
|
||||
|
||||
// For all objects but the receiver, check that the cache is empty.
|
||||
NearLabel check_prototype;
|
||||
Label check_prototype;
|
||||
__ cmp(ecx, Operand(eax));
|
||||
__ j(equal, &check_prototype);
|
||||
__ j(equal, &check_prototype, Label::kNear);
|
||||
__ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
||||
__ cmp(edx, isolate()->factory()->empty_fixed_array());
|
||||
__ j(not_equal, &call_runtime);
|
||||
@ -918,9 +918,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// The enum cache is valid. Load the map of the object being
|
||||
// iterated over and use the cache for the iteration.
|
||||
NearLabel use_cache;
|
||||
Label use_cache;
|
||||
__ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ jmp(&use_cache);
|
||||
__ jmp(&use_cache, Label::kNear);
|
||||
|
||||
// Get the set of properties to enumerate.
|
||||
__ bind(&call_runtime);
|
||||
@ -930,10 +930,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// If we got a map from the runtime call, we can do a fast
|
||||
// modification check. Otherwise, we got a fixed array, and we have
|
||||
// to do a slow check.
|
||||
NearLabel fixed_array;
|
||||
Label fixed_array;
|
||||
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
|
||||
isolate()->factory()->meta_map());
|
||||
__ j(not_equal, &fixed_array);
|
||||
__ j(not_equal, &fixed_array, Label::kNear);
|
||||
|
||||
// We got a map in register eax. Get the enumeration cache from it.
|
||||
__ bind(&use_cache);
|
||||
@ -973,10 +973,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Check if the expected map still matches that of the enumerable.
|
||||
// If not, we have to filter the key.
|
||||
NearLabel update_each;
|
||||
Label update_each;
|
||||
__ mov(ecx, Operand(esp, 4 * kPointerSize));
|
||||
__ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
|
||||
__ j(equal, &update_each);
|
||||
__ j(equal, &update_each, Label::kNear);
|
||||
|
||||
// Convert the entry to a string or null if it isn't a property
|
||||
// anymore. If the property has been removed while iterating, we
|
||||
@ -1084,7 +1084,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
|
||||
if (s != NULL && s->is_eval_scope()) {
|
||||
// Loop up the context chain. There is no frame effect so it is
|
||||
// safe to use raw labels here.
|
||||
NearLabel next, fast;
|
||||
Label next, fast;
|
||||
if (!context.is(temp)) {
|
||||
__ mov(temp, context);
|
||||
}
|
||||
@ -1092,7 +1092,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
|
||||
// Terminate at global context.
|
||||
__ cmp(FieldOperand(temp, HeapObject::kMapOffset),
|
||||
Immediate(isolate()->factory()->global_context_map()));
|
||||
__ j(equal, &fast);
|
||||
__ j(equal, &fast, Label::kNear);
|
||||
// Check that extension is NULL.
|
||||
__ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
|
||||
__ j(not_equal, slow);
|
||||
@ -1241,11 +1241,11 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
|
||||
if (var->mode() == Variable::CONST) {
|
||||
// Constants may be the hole value if they have not been initialized.
|
||||
// Unhole them.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
MemOperand slot_operand = EmitSlotSearch(slot, eax);
|
||||
__ mov(eax, slot_operand);
|
||||
__ cmp(eax, isolate()->factory()->the_hole_value());
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
__ mov(eax, isolate()->factory()->undefined_value());
|
||||
__ bind(&done);
|
||||
context()->Plug(eax);
|
||||
@ -1288,7 +1288,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
|
||||
|
||||
void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ RegExpLiteral");
|
||||
NearLabel materialized;
|
||||
Label materialized;
|
||||
// Registers will be used as follows:
|
||||
// edi = JS function.
|
||||
// ecx = literals array.
|
||||
@ -1300,7 +1300,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
|
||||
__ mov(ebx, FieldOperand(ecx, literal_offset));
|
||||
__ cmp(ebx, isolate()->factory()->undefined_value());
|
||||
__ j(not_equal, &materialized);
|
||||
__ j(not_equal, &materialized, Label::kNear);
|
||||
|
||||
// Create regexp literal using runtime function
|
||||
// Result will be in eax.
|
||||
@ -1657,7 +1657,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
Expression* right) {
|
||||
// Do combined smi check of the operands. Left operand is on the
|
||||
// stack. Right operand is in eax.
|
||||
NearLabel done, smi_case, stub_call;
|
||||
NearLabel smi_case;
|
||||
Label done, stub_call;
|
||||
__ pop(edx);
|
||||
__ mov(ecx, eax);
|
||||
__ or_(eax, Operand(edx));
|
||||
@ -1668,7 +1669,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
__ mov(eax, ecx);
|
||||
TypeRecordingBinaryOpStub stub(op, mode);
|
||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Smi case.
|
||||
__ bind(&smi_case);
|
||||
@ -1721,7 +1722,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
__ imul(eax, Operand(ecx));
|
||||
__ j(overflow, &stub_call);
|
||||
__ test(eax, Operand(eax));
|
||||
__ j(not_zero, &done, taken);
|
||||
__ j(not_zero, &done, taken, Label::kNear);
|
||||
__ mov(ebx, edx);
|
||||
__ or_(ebx, Operand(ecx));
|
||||
__ j(negative, &stub_call);
|
||||
@ -2843,13 +2844,13 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
||||
|
||||
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
// If the object is a smi return the object.
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
// If the object is not a value type, return the object.
|
||||
__ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
__ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
|
||||
|
||||
__ bind(&done);
|
||||
@ -2880,14 +2881,14 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
||||
VisitForAccumulatorValue(args->at(1)); // Load the value.
|
||||
__ pop(ebx); // eax = value. ebx = object.
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
// If the object is a smi, return the value.
|
||||
__ test(ebx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
|
||||
// If the object is not a value type, return the value.
|
||||
__ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Store the value.
|
||||
__ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
|
||||
@ -3829,10 +3830,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
// Call ToNumber only if operand is not a smi.
|
||||
NearLabel no_conversion;
|
||||
Label no_conversion;
|
||||
if (ShouldInlineSmiCase(expr->op())) {
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &no_conversion);
|
||||
__ j(zero, &no_conversion, Label::kNear);
|
||||
}
|
||||
ToNumberStub convert_stub;
|
||||
__ CallStub(&convert_stub);
|
||||
@ -3859,7 +3860,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
// Inline smi case if we are in a loop.
|
||||
NearLabel stub_call, done;
|
||||
NearLabel done;
|
||||
Label stub_call;
|
||||
JumpPatchSite patch_site(masm_);
|
||||
|
||||
if (ShouldInlineSmiCase(expr->op())) {
|
||||
@ -3868,7 +3870,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
} else {
|
||||
__ sub(Operand(eax), Immediate(Smi::FromInt(1)));
|
||||
}
|
||||
__ j(overflow, &stub_call);
|
||||
__ j(overflow, &stub_call, Label::kNear);
|
||||
// We could eliminate this smi check if we split the code at
|
||||
// the first smi check before calling ToNumber.
|
||||
patch_site.EmitJumpIfSmi(eax, &done);
|
||||
|
@ -97,7 +97,6 @@ static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Helper function used to load a property from a dictionary backing
|
||||
// storage. This function may fail to load a property even though it is
|
||||
// in the dictionary, so code at miss_label must always call a backup
|
||||
@ -749,7 +748,8 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
// ecx: key, a smi.
|
||||
// edi: receiver->elements, a FixedArray
|
||||
// flags: compare (ecx, edx.length())
|
||||
__ j(not_equal, &slow, not_taken); // do not leave holes in the array
|
||||
// do not leave holes in the array:
|
||||
__ j(not_equal, &slow, not_taken);
|
||||
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
|
||||
__ j(above_equal, &slow, not_taken);
|
||||
// Add 1 to receiver->length, and go to fast array write.
|
||||
@ -942,13 +942,13 @@ static void GenerateCallMiss(MacroAssembler* masm,
|
||||
Label invoke, global;
|
||||
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
|
||||
__ test(edx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &invoke, not_taken);
|
||||
__ j(zero, &invoke, not_taken, Label::kNear);
|
||||
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
__ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
|
||||
__ j(equal, &global);
|
||||
__ j(equal, &global, Label::kNear);
|
||||
__ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
|
||||
__ j(not_equal, &invoke);
|
||||
__ j(not_equal, &invoke, Label::kNear);
|
||||
|
||||
// Patch the receiver on the stack.
|
||||
__ bind(&global);
|
||||
|
@ -545,7 +545,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
|
||||
__ mov(ebx, shared);
|
||||
__ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset));
|
||||
__ sub(Operand(eax), Immediate(Smi::FromInt(1)));
|
||||
__ j(not_zero, &no_deopt);
|
||||
__ j(not_zero, &no_deopt, Label::kNear);
|
||||
if (FLAG_trap_on_deopt) __ int3();
|
||||
__ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times)));
|
||||
__ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax);
|
||||
@ -566,8 +566,8 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
|
||||
__ jmp(entry, RelocInfo::RUNTIME_ENTRY);
|
||||
} else {
|
||||
if (FLAG_trap_on_deopt) {
|
||||
NearLabel done;
|
||||
__ j(NegateCondition(cc), &done);
|
||||
Label done;
|
||||
__ j(NegateCondition(cc), &done, Label::kNear);
|
||||
__ int3();
|
||||
__ jmp(entry, RelocInfo::RUNTIME_ENTRY);
|
||||
__ bind(&done);
|
||||
@ -787,21 +787,21 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
|
||||
if (divisor < 0) divisor = -divisor;
|
||||
|
||||
NearLabel positive_dividend, done;
|
||||
Label positive_dividend, done;
|
||||
__ test(dividend, Operand(dividend));
|
||||
__ j(not_sign, &positive_dividend);
|
||||
__ j(not_sign, &positive_dividend, Label::kNear);
|
||||
__ neg(dividend);
|
||||
__ and_(dividend, divisor - 1);
|
||||
__ neg(dividend);
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
}
|
||||
__ bind(&positive_dividend);
|
||||
__ and_(dividend, divisor - 1);
|
||||
__ bind(&done);
|
||||
} else {
|
||||
NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Register left_reg = ToRegister(instr->InputAt(0));
|
||||
Register right_reg = ToRegister(instr->InputAt(1));
|
||||
Register result_reg = ToRegister(instr->result());
|
||||
@ -818,11 +818,11 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
}
|
||||
|
||||
__ test(left_reg, Operand(left_reg));
|
||||
__ j(zero, &remainder_eq_dividend);
|
||||
__ j(sign, &slow);
|
||||
__ j(zero, &remainder_eq_dividend, Label::kNear);
|
||||
__ j(sign, &slow, Label::kNear);
|
||||
|
||||
__ test(right_reg, Operand(right_reg));
|
||||
__ j(not_sign, &both_positive);
|
||||
__ j(not_sign, &both_positive, Label::kNear);
|
||||
// The sign of the divisor doesn't matter.
|
||||
__ neg(right_reg);
|
||||
|
||||
@ -830,16 +830,16 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
// If the dividend is smaller than the nonnegative
|
||||
// divisor, the dividend is the result.
|
||||
__ cmp(left_reg, Operand(right_reg));
|
||||
__ j(less, &remainder_eq_dividend);
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
|
||||
// Check if the divisor is a PowerOfTwo integer.
|
||||
Register scratch = ToRegister(instr->TempAt(0));
|
||||
__ mov(scratch, right_reg);
|
||||
__ sub(Operand(scratch), Immediate(1));
|
||||
__ test(scratch, Operand(right_reg));
|
||||
__ j(not_zero, &do_subtraction);
|
||||
__ j(not_zero, &do_subtraction, Label::kNear);
|
||||
__ and_(left_reg, Operand(scratch));
|
||||
__ jmp(&remainder_eq_dividend);
|
||||
__ jmp(&remainder_eq_dividend, Label::kNear);
|
||||
|
||||
__ bind(&do_subtraction);
|
||||
const int kUnfolds = 3;
|
||||
@ -850,7 +850,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ sub(left_reg, Operand(right_reg));
|
||||
// Check if the dividend is less than the divisor.
|
||||
__ cmp(left_reg, Operand(right_reg));
|
||||
__ j(less, &remainder_eq_dividend);
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
}
|
||||
__ mov(left_reg, scratch);
|
||||
|
||||
@ -861,15 +861,15 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
|
||||
// Check for (0 % -x) that will produce negative zero.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel positive_left;
|
||||
NearLabel done;
|
||||
Label positive_left;
|
||||
Label done;
|
||||
__ test(left_reg, Operand(left_reg));
|
||||
__ j(not_sign, &positive_left);
|
||||
__ j(not_sign, &positive_left, Label::kNear);
|
||||
__ idiv(right_reg);
|
||||
|
||||
// Test the remainder for 0, because then the result would be -0.
|
||||
__ test(result_reg, Operand(result_reg));
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
__ bind(&positive_left);
|
||||
@ -878,7 +878,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
} else {
|
||||
__ idiv(right_reg);
|
||||
}
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&remainder_eq_dividend);
|
||||
__ mov(result_reg, left_reg);
|
||||
@ -906,9 +906,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
||||
|
||||
// Check for (0 / -x) that will produce negative zero.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel left_not_zero;
|
||||
Label left_not_zero;
|
||||
__ test(left_reg, Operand(left_reg));
|
||||
__ j(not_zero, &left_not_zero);
|
||||
__ j(not_zero, &left_not_zero, Label::kNear);
|
||||
__ test(right_reg, ToOperand(right));
|
||||
DeoptimizeIf(sign, instr->environment());
|
||||
__ bind(&left_not_zero);
|
||||
@ -916,9 +916,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
||||
|
||||
// Check for (-kMinInt / -1).
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
|
||||
NearLabel left_not_min_int;
|
||||
Label left_not_min_int;
|
||||
__ cmp(left_reg, kMinInt);
|
||||
__ j(not_zero, &left_not_min_int);
|
||||
__ j(not_zero, &left_not_min_int, Label::kNear);
|
||||
__ cmp(right_reg, -1);
|
||||
DeoptimizeIf(zero, instr->environment());
|
||||
__ bind(&left_not_min_int);
|
||||
@ -996,9 +996,9 @@ void LCodeGen::DoMulI(LMulI* instr) {
|
||||
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
// Bail out if the result is supposed to be negative zero.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ test(left, Operand(left));
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
if (right->IsConstantOperand()) {
|
||||
if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
@ -1203,14 +1203,14 @@ void LCodeGen::DoValueOf(LValueOf* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
Register map = ToRegister(instr->TempAt(0));
|
||||
ASSERT(input.is(result));
|
||||
NearLabel done;
|
||||
Label done;
|
||||
// If the object is a smi return the object.
|
||||
__ test(input, Immediate(kSmiTagMask));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
|
||||
// If the object is not a value type, return the object.
|
||||
__ CmpObjectType(input, JS_VALUE_TYPE, map);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
__ mov(result, FieldOperand(input, JSValue::kValueOffset));
|
||||
|
||||
__ bind(&done);
|
||||
@ -1368,10 +1368,10 @@ void LCodeGen::DoBranch(LBranch* instr) {
|
||||
__ j(zero, true_label);
|
||||
|
||||
// Test for double values. Zero is false.
|
||||
NearLabel call_stub;
|
||||
Label call_stub;
|
||||
__ cmp(FieldOperand(reg, HeapObject::kMapOffset),
|
||||
factory()->heap_number_map());
|
||||
__ j(not_equal, &call_stub);
|
||||
__ j(not_equal, &call_stub, Label::kNear);
|
||||
__ fldz();
|
||||
__ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
|
||||
__ FCmp();
|
||||
@ -1477,20 +1477,20 @@ void LCodeGen::DoCmpID(LCmpID* instr) {
|
||||
LOperand* right = instr->InputAt(1);
|
||||
LOperand* result = instr->result();
|
||||
|
||||
NearLabel unordered;
|
||||
Label unordered;
|
||||
if (instr->is_double()) {
|
||||
// Don't base result on EFLAGS when a NaN is involved. Instead
|
||||
// jump to the unordered case, which produces a false value.
|
||||
__ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
|
||||
__ j(parity_even, &unordered, not_taken);
|
||||
__ j(parity_even, &unordered, not_taken, Label::kNear);
|
||||
} else {
|
||||
EmitCmpI(left, right);
|
||||
}
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
||||
__ mov(ToRegister(result), factory()->true_value());
|
||||
__ j(cc, &done);
|
||||
__ j(cc, &done, Label::kNear);
|
||||
|
||||
__ bind(&unordered);
|
||||
__ mov(ToRegister(result), factory()->false_value());
|
||||
@ -1525,8 +1525,8 @@ void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
|
||||
|
||||
__ cmp(left, Operand(right));
|
||||
__ mov(result, factory()->true_value());
|
||||
NearLabel done;
|
||||
__ j(equal, &done);
|
||||
Label done;
|
||||
__ j(equal, &done, Label::kNear);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ bind(&done);
|
||||
}
|
||||
@ -1553,27 +1553,27 @@ void LCodeGen::DoIsNull(LIsNull* instr) {
|
||||
__ cmp(reg, factory()->null_value());
|
||||
if (instr->is_strict()) {
|
||||
__ mov(result, factory()->true_value());
|
||||
NearLabel done;
|
||||
__ j(equal, &done);
|
||||
Label done;
|
||||
__ j(equal, &done, Label::kNear);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ bind(&done);
|
||||
} else {
|
||||
NearLabel true_value, false_value, done;
|
||||
__ j(equal, &true_value);
|
||||
Label true_value, false_value, done;
|
||||
__ j(equal, &true_value, Label::kNear);
|
||||
__ cmp(reg, factory()->undefined_value());
|
||||
__ j(equal, &true_value);
|
||||
__ j(equal, &true_value, Label::kNear);
|
||||
__ test(reg, Immediate(kSmiTagMask));
|
||||
__ j(zero, &false_value);
|
||||
__ j(zero, &false_value, Label::kNear);
|
||||
// Check for undetectable objects by looking in the bit field in
|
||||
// the map. The object has already been smi checked.
|
||||
Register scratch = result;
|
||||
__ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
|
||||
__ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
|
||||
__ test(scratch, Immediate(1 << Map::kIsUndetectable));
|
||||
__ j(not_zero, &true_value);
|
||||
__ j(not_zero, &true_value, Label::kNear);
|
||||
__ bind(&false_value);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ mov(result, factory()->true_value());
|
||||
__ bind(&done);
|
||||
@ -1684,8 +1684,8 @@ void LCodeGen::DoIsSmi(LIsSmi* instr) {
|
||||
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
||||
__ test(input, Immediate(kSmiTagMask));
|
||||
__ mov(result, factory()->true_value());
|
||||
NearLabel done;
|
||||
__ j(zero, &done);
|
||||
Label done;
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ bind(&done);
|
||||
}
|
||||
@ -1728,12 +1728,13 @@ void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
|
||||
|
||||
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
||||
__ test(input, Immediate(kSmiTagMask));
|
||||
NearLabel done, is_false;
|
||||
__ j(zero, &is_false);
|
||||
Label done, is_false;
|
||||
__ j(zero, &is_false, Label::kNear);
|
||||
__ CmpObjectType(input, TestType(instr->hydrogen()), result);
|
||||
__ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
|
||||
__ j(NegateCondition(BranchCondition(instr->hydrogen())),
|
||||
&is_false, Label::kNear);
|
||||
__ mov(result, factory()->true_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&is_false);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ bind(&done);
|
||||
@ -1778,8 +1779,8 @@ void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
|
||||
__ mov(result, factory()->true_value());
|
||||
__ test(FieldOperand(input, String::kHashFieldOffset),
|
||||
Immediate(String::kContainsCachedArrayIndexMask));
|
||||
NearLabel done;
|
||||
__ j(zero, &done);
|
||||
Label done;
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ bind(&done);
|
||||
}
|
||||
@ -1861,16 +1862,16 @@ void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
|
||||
ASSERT(input.is(result));
|
||||
Register temp = ToRegister(instr->TempAt(0));
|
||||
Handle<String> class_name = instr->hydrogen()->class_name();
|
||||
NearLabel done;
|
||||
Label done;
|
||||
Label is_true, is_false;
|
||||
|
||||
EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input);
|
||||
|
||||
__ j(not_equal, &is_false);
|
||||
__ j(not_equal, &is_false, Label::kNear);
|
||||
|
||||
__ bind(&is_true);
|
||||
__ mov(result, factory()->true_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&is_false);
|
||||
__ mov(result, factory()->false_value());
|
||||
@ -1918,11 +1919,11 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
||||
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
|
||||
|
||||
NearLabel true_value, done;
|
||||
Label true_value, done;
|
||||
__ test(eax, Operand(eax));
|
||||
__ j(zero, &true_value);
|
||||
__ j(zero, &true_value, Label::kNear);
|
||||
__ mov(ToRegister(instr->result()), factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ mov(ToRegister(instr->result()), factory()->true_value());
|
||||
__ bind(&done);
|
||||
@ -1972,12 +1973,12 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
||||
// This is the inlined call site instanceof cache. The two occurences of the
|
||||
// hole value will be patched to the last map/result pair generated by the
|
||||
// instanceof stub.
|
||||
NearLabel cache_miss;
|
||||
Label cache_miss;
|
||||
Register map = ToRegister(instr->TempAt(0));
|
||||
__ mov(map, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ bind(deferred->map_check()); // Label for calculating code patching.
|
||||
__ cmp(map, factory()->the_hole_value()); // Patched to cached map.
|
||||
__ j(not_equal, &cache_miss, not_taken);
|
||||
__ j(not_equal, &cache_miss, not_taken, Label::kNear);
|
||||
__ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
|
||||
__ jmp(&done);
|
||||
|
||||
@ -2069,11 +2070,11 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
|
||||
if (op == Token::GT || op == Token::LTE) {
|
||||
condition = ReverseCondition(condition);
|
||||
}
|
||||
NearLabel true_value, done;
|
||||
Label true_value, done;
|
||||
__ test(eax, Operand(eax));
|
||||
__ j(condition, &true_value);
|
||||
__ j(condition, &true_value, Label::kNear);
|
||||
__ mov(ToRegister(instr->result()), factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ mov(ToRegister(instr->result()), factory()->true_value());
|
||||
__ bind(&done);
|
||||
@ -2239,23 +2240,23 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
|
||||
} else {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
for (int i = 0; i < map_count - 1; ++i) {
|
||||
Handle<Map> map = instr->hydrogen()->types()->at(i);
|
||||
NearLabel next;
|
||||
Label next;
|
||||
__ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
|
||||
__ j(not_equal, &next);
|
||||
__ j(not_equal, &next, Label::kNear);
|
||||
EmitLoadFieldOrConstantFunction(result, object, map, name);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&next);
|
||||
}
|
||||
Handle<Map> map = instr->hydrogen()->types()->last();
|
||||
__ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
|
||||
if (instr->hydrogen()->need_generic()) {
|
||||
NearLabel generic;
|
||||
__ j(not_equal, &generic);
|
||||
Label generic;
|
||||
__ j(not_equal, &generic, Label::kNear);
|
||||
EmitLoadFieldOrConstantFunction(result, object, map, name);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&generic);
|
||||
__ mov(ecx, name);
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
@ -2290,10 +2291,10 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||
DeoptimizeIf(not_equal, instr->environment());
|
||||
|
||||
// Check whether the function has an instance prototype.
|
||||
NearLabel non_instance;
|
||||
Label non_instance;
|
||||
__ test_b(FieldOperand(result, Map::kBitFieldOffset),
|
||||
1 << Map::kHasNonInstancePrototype);
|
||||
__ j(not_zero, &non_instance);
|
||||
__ j(not_zero, &non_instance, Label::kNear);
|
||||
|
||||
// Get the prototype or initial map from the function.
|
||||
__ mov(result,
|
||||
@ -2304,13 +2305,13 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||
DeoptimizeIf(equal, instr->environment());
|
||||
|
||||
// If the function does not have an initial map, we're done.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ CmpObjectType(result, MAP_TYPE, temp);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Get the prototype from the initial map.
|
||||
__ mov(result, FieldOperand(result, Map::kPrototypeOffset));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Non-instance prototype: Fetch prototype from constructor field
|
||||
// in the function's map.
|
||||
@ -2327,13 +2328,13 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
||||
Register input = ToRegister(instr->InputAt(0));
|
||||
__ mov(result, FieldOperand(input, JSObject::kElementsOffset));
|
||||
if (FLAG_debug_code) {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ cmp(FieldOperand(result, HeapObject::kMapOffset),
|
||||
Immediate(factory()->fixed_array_map()));
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
__ cmp(FieldOperand(result, HeapObject::kMapOffset),
|
||||
Immediate(factory()->fixed_cow_array_map()));
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
Register temp((result.is(eax)) ? ebx : eax);
|
||||
__ push(temp);
|
||||
__ mov(temp, FieldOperand(result, HeapObject::kMapOffset));
|
||||
@ -2453,16 +2454,16 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
// Check for arguments adapter frame.
|
||||
NearLabel done, adapted;
|
||||
Label done, adapted;
|
||||
__ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
|
||||
__ cmp(Operand(result),
|
||||
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
__ j(equal, &adapted);
|
||||
__ j(equal, &adapted, Label::kNear);
|
||||
|
||||
// No arguments adaptor frame.
|
||||
__ mov(result, Operand(ebp));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Arguments adaptor frame present.
|
||||
__ bind(&adapted);
|
||||
@ -2478,12 +2479,12 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
||||
Operand elem = ToOperand(instr->InputAt(0));
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
|
||||
// If no arguments adaptor frame the number of arguments is fixed.
|
||||
__ cmp(ebp, elem);
|
||||
__ mov(result, Immediate(scope()->num_parameters()));
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
|
||||
// Arguments adaptor frame present. Get argument length from there.
|
||||
__ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
||||
@ -2508,18 +2509,18 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
||||
|
||||
// If the receiver is null or undefined, we have to pass the global object
|
||||
// as a receiver.
|
||||
NearLabel global_object, receiver_ok;
|
||||
Label global_object, receiver_ok;
|
||||
__ cmp(receiver, factory()->null_value());
|
||||
__ j(equal, &global_object);
|
||||
__ j(equal, &global_object, Label::kNear);
|
||||
__ cmp(receiver, factory()->undefined_value());
|
||||
__ j(equal, &global_object);
|
||||
__ j(equal, &global_object, Label::kNear);
|
||||
|
||||
// The receiver should be a JS object.
|
||||
__ test(receiver, Immediate(kSmiTagMask));
|
||||
DeoptimizeIf(equal, instr->environment());
|
||||
__ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch);
|
||||
DeoptimizeIf(below, instr->environment());
|
||||
__ jmp(&receiver_ok);
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
|
||||
__ bind(&global_object);
|
||||
// TODO(kmillikin): We have a hydrogen value for the global object. See
|
||||
@ -2540,10 +2541,10 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
||||
|
||||
// Loop through the arguments pushing them onto the execution
|
||||
// stack.
|
||||
NearLabel invoke, loop;
|
||||
Label invoke, loop;
|
||||
// length is a small non-negative integer, due to the test above.
|
||||
__ test(length, Operand(length));
|
||||
__ j(zero, &invoke);
|
||||
__ j(zero, &invoke, Label::kNear);
|
||||
__ bind(&loop);
|
||||
__ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
|
||||
__ dec(length);
|
||||
@ -2895,20 +2896,20 @@ void LCodeGen::DoPower(LPower* instr) {
|
||||
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
|
||||
ASSERT(instr->InputAt(0)->Equals(instr->result()));
|
||||
XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
||||
NearLabel positive, done, zero, negative;
|
||||
Label positive, done, zero;
|
||||
__ xorps(xmm0, xmm0);
|
||||
__ ucomisd(input_reg, xmm0);
|
||||
__ j(above, &positive);
|
||||
__ j(equal, &zero);
|
||||
__ j(above, &positive, Label::kNear);
|
||||
__ j(equal, &zero, Label::kNear);
|
||||
ExternalReference nan = ExternalReference::address_of_nan();
|
||||
__ movdbl(input_reg, Operand::StaticVariable(nan));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&zero);
|
||||
__ push(Immediate(0xFFF00000));
|
||||
__ push(Immediate(0));
|
||||
__ movdbl(input_reg, Operand(esp, 0));
|
||||
__ add(Operand(esp), Immediate(kDoubleSize));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&positive);
|
||||
__ fldln2();
|
||||
__ sub(Operand(esp), Immediate(kDoubleSize));
|
||||
@ -3128,9 +3129,9 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
// instruction.
|
||||
ASSERT(temp.is(eax));
|
||||
__ mov(temp, ToRegister(instr->value()));
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ test(temp, Immediate(0xFFFFFF00));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ setcc(negative, temp); // 1 if negative, 0 if positive.
|
||||
__ dec_b(temp); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
@ -3237,7 +3238,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
DeferredStringCharCodeAt* deferred =
|
||||
new DeferredStringCharCodeAt(this, instr);
|
||||
|
||||
NearLabel flat_string, ascii_string, done;
|
||||
Label flat_string, ascii_string, done;
|
||||
|
||||
// Fetch the instance type of the receiver into result register.
|
||||
__ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
@ -3246,7 +3247,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
// We need special handling for non-flat strings.
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ test(result, Immediate(kStringRepresentationMask));
|
||||
__ j(zero, &flat_string);
|
||||
__ j(zero, &flat_string, Label::kNear);
|
||||
|
||||
// Handle non-flat strings.
|
||||
__ test(result, Immediate(kIsConsStringMask));
|
||||
@ -3273,7 +3274,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
__ bind(&flat_string);
|
||||
STATIC_ASSERT(kAsciiStringTag != 0);
|
||||
__ test(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string);
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
@ -3289,7 +3290,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
times_2,
|
||||
SeqTwoByteString::kHeaderSize));
|
||||
}
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
@ -3450,13 +3451,13 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
|
||||
// There was overflow, so bits 30 and 31 of the original integer
|
||||
// disagree. Try to allocate a heap number in new space and store
|
||||
// the value in there. If that fails, call the runtime system.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ SmiUntag(reg);
|
||||
__ xor_(reg, 0x80000000);
|
||||
__ cvtsi2sd(xmm0, Operand(reg));
|
||||
if (FLAG_inline_new) {
|
||||
__ AllocateHeapNumber(reg, tmp, no_reg, &slow);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
}
|
||||
|
||||
// Slow case: Call the runtime system to do the number allocation.
|
||||
@ -3538,16 +3539,16 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
||||
void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||
XMMRegister result_reg,
|
||||
LEnvironment* env) {
|
||||
NearLabel load_smi, heap_number, done;
|
||||
Label load_smi, heap_number, done;
|
||||
|
||||
// Smi check.
|
||||
__ test(input_reg, Immediate(kSmiTagMask));
|
||||
__ j(zero, &load_smi, not_taken);
|
||||
__ j(zero, &load_smi, not_taken, Label::kNear);
|
||||
|
||||
// Heap number map check.
|
||||
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
|
||||
factory()->heap_number_map());
|
||||
__ j(equal, &heap_number);
|
||||
__ j(equal, &heap_number, Label::kNear);
|
||||
|
||||
__ cmp(input_reg, factory()->undefined_value());
|
||||
DeoptimizeIf(not_equal, env);
|
||||
@ -3555,12 +3556,12 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||
// Convert undefined to NaN.
|
||||
ExternalReference nan = ExternalReference::address_of_nan();
|
||||
__ movdbl(result_reg, Operand::StaticVariable(nan));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Heap number to XMM conversion.
|
||||
__ bind(&heap_number);
|
||||
__ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Smi to XMM conversion
|
||||
__ bind(&load_smi);
|
||||
@ -3582,7 +3583,7 @@ class DeferredTaggedToI: public LDeferredCode {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
NearLabel done, heap_number;
|
||||
Label done, heap_number;
|
||||
Register input_reg = ToRegister(instr->InputAt(0));
|
||||
|
||||
// Heap number map check.
|
||||
@ -3590,18 +3591,18 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
factory()->heap_number_map());
|
||||
|
||||
if (instr->truncating()) {
|
||||
__ j(equal, &heap_number);
|
||||
__ j(equal, &heap_number, Label::kNear);
|
||||
// Check for undefined. Undefined is converted to zero for truncating
|
||||
// conversions.
|
||||
__ cmp(input_reg, factory()->undefined_value());
|
||||
DeoptimizeIf(not_equal, instr->environment());
|
||||
__ mov(input_reg, 0);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&heap_number);
|
||||
if (CpuFeatures::IsSupported(SSE3)) {
|
||||
CpuFeatures::Scope scope(SSE3);
|
||||
NearLabel convert;
|
||||
Label convert;
|
||||
// Use more powerful conversion when sse3 is available.
|
||||
// Load x87 register with heap number.
|
||||
__ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
|
||||
@ -3611,7 +3612,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
const uint32_t kTooBigExponent =
|
||||
(HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
|
||||
__ cmp(Operand(input_reg), Immediate(kTooBigExponent));
|
||||
__ j(less, &convert);
|
||||
__ j(less, &convert, Label::kNear);
|
||||
// Pop FPU stack before deoptimizing.
|
||||
__ ffree(0);
|
||||
__ fincstp();
|
||||
@ -3625,7 +3626,6 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
__ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result.
|
||||
__ add(Operand(esp), Immediate(kDoubleSize));
|
||||
} else {
|
||||
NearLabel deopt;
|
||||
XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0));
|
||||
__ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
|
||||
__ cvttsd2si(input_reg, Operand(xmm0));
|
||||
@ -3712,8 +3712,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
if (CpuFeatures::IsSupported(SSE3)) {
|
||||
// This will deoptimize if the exponent of the input in out of range.
|
||||
CpuFeatures::Scope scope(SSE3);
|
||||
NearLabel convert, done;
|
||||
__ j(not_equal, &done);
|
||||
Label convert, done;
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
__ sub(Operand(esp), Immediate(kDoubleSize));
|
||||
__ movdbl(Operand(esp, 0), input_reg);
|
||||
// Get exponent alone and check for too-big exponent.
|
||||
@ -3722,7 +3722,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
const uint32_t kTooBigExponent =
|
||||
(HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
|
||||
__ cmp(Operand(result_reg), Immediate(kTooBigExponent));
|
||||
__ j(less, &convert);
|
||||
__ j(less, &convert, Label::kNear);
|
||||
__ add(Operand(esp), Immediate(kDoubleSize));
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
__ bind(&convert);
|
||||
@ -3733,13 +3733,13 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
__ add(Operand(esp), Immediate(kDoubleSize));
|
||||
__ bind(&done);
|
||||
} else {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
Register temp_reg = ToRegister(instr->TempAt(0));
|
||||
XMMRegister xmm_scratch = xmm0;
|
||||
|
||||
// If cvttsd2si succeeded, we're done. Otherwise, we attempt
|
||||
// manual conversion.
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Get high 32 bits of the input in result_reg and temp_reg.
|
||||
__ pshufd(xmm_scratch, input_reg, 1);
|
||||
@ -3789,7 +3789,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
__ bind(&done);
|
||||
}
|
||||
} else {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ cvttsd2si(result_reg, Operand(input_reg));
|
||||
__ cvtsi2sd(xmm0, Operand(result_reg));
|
||||
__ ucomisd(xmm0, input_reg);
|
||||
@ -3799,7 +3799,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
// The integer converted back is equal to the original. We
|
||||
// only have to test if we got -0 as an input.
|
||||
__ test(result_reg, Operand(result_reg));
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
__ movmskpd(result_reg, input_reg);
|
||||
// Bit 0 contains the sign of the double in input_reg.
|
||||
// If input was positive, we are ok and return 0, otherwise
|
||||
@ -3976,7 +3976,7 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
||||
NearLabel materialized;
|
||||
Label materialized;
|
||||
// Registers will be used as follows:
|
||||
// edi = JS function.
|
||||
// ecx = literals array.
|
||||
@ -3988,7 +3988,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
||||
instr->hydrogen()->literal_index() * kPointerSize;
|
||||
__ mov(ebx, FieldOperand(ecx, literal_offset));
|
||||
__ cmp(ebx, factory()->undefined_value());
|
||||
__ j(not_equal, &materialized);
|
||||
__ j(not_equal, &materialized, Label::kNear);
|
||||
|
||||
// Create regexp literal using runtime function
|
||||
// Result will be in eax.
|
||||
@ -4064,16 +4064,16 @@ void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
Label true_label;
|
||||
Label false_label;
|
||||
NearLabel done;
|
||||
Label done;
|
||||
|
||||
Condition final_branch_condition = EmitTypeofIs(&true_label,
|
||||
&false_label,
|
||||
input,
|
||||
instr->type_literal());
|
||||
__ j(final_branch_condition, &true_label);
|
||||
__ j(final_branch_condition, &true_label, Label::kNear);
|
||||
__ bind(&false_label);
|
||||
__ mov(result, factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&true_label);
|
||||
__ mov(result, factory()->true_value());
|
||||
@ -4167,15 +4167,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
|
||||
void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
NearLabel true_label;
|
||||
NearLabel false_label;
|
||||
NearLabel done;
|
||||
Label true_label;
|
||||
Label done;
|
||||
|
||||
EmitIsConstructCall(result);
|
||||
__ j(equal, &true_label);
|
||||
__ j(equal, &true_label, Label::kNear);
|
||||
|
||||
__ mov(result, factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&true_label);
|
||||
__ mov(result, factory()->true_value());
|
||||
@ -4199,10 +4198,10 @@ void LCodeGen::EmitIsConstructCall(Register temp) {
|
||||
__ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
||||
|
||||
// Skip the arguments adaptor frame if it exists.
|
||||
NearLabel check_frame_marker;
|
||||
Label check_frame_marker;
|
||||
__ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
|
||||
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
__ j(not_equal, &check_frame_marker);
|
||||
__ j(not_equal, &check_frame_marker, Label::kNear);
|
||||
__ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
|
||||
|
||||
// Check the marker in the calling frame.
|
||||
@ -4251,11 +4250,11 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
|
||||
|
||||
void LCodeGen::DoStackCheck(LStackCheck* instr) {
|
||||
// Perform stack overflow check.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
ExternalReference stack_limit =
|
||||
ExternalReference::address_of_stack_limit(isolate());
|
||||
__ cmp(esp, Operand::StaticVariable(stack_limit));
|
||||
__ j(above_equal, &done);
|
||||
__ j(above_equal, &done, Label::kNear);
|
||||
|
||||
StackCheckStub stub;
|
||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
|
||||
|
@ -484,9 +484,9 @@ void MacroAssembler::Throw(Register value) {
|
||||
// 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, not_taken, Label::kNear);
|
||||
mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
||||
bind(&skip);
|
||||
|
||||
@ -511,12 +511,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
|
||||
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));
|
||||
|
@ -971,9 +971,9 @@ void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
|
||||
}
|
||||
|
||||
void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) {
|
||||
NearLabel after_position;
|
||||
Label after_position;
|
||||
__ cmp(edi, -by * char_size());
|
||||
__ j(greater_equal, &after_position);
|
||||
__ j(greater_equal, &after_position, Label::kNear);
|
||||
__ mov(edi, -by * char_size());
|
||||
// On RegExp code entry (where this operation is used), the character before
|
||||
// the current position is expected to be already loaded.
|
||||
|
@ -3511,9 +3511,9 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
{ // Clamp the value to [0..255].
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ test(ecx, Immediate(0xFFFFFF00));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ setcc(negative, ecx); // 1 if negative, 0 if positive.
|
||||
__ dec_b(ecx); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
@ -3594,9 +3594,9 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
{ // Clamp the value to [0..255].
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ test(ecx, Immediate(0xFFFFFF00));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ setcc(negative, ecx); // 1 if negative, 0 if positive.
|
||||
__ dec_b(ecx); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
|
@ -458,6 +458,20 @@ void Assembler::bind_to(Label* L, int pos) {
|
||||
int last_imm32 = pos - (current + sizeof(int32_t));
|
||||
long_at_put(current, last_imm32);
|
||||
}
|
||||
while (L->is_near_linked()) {
|
||||
int fixup_pos = L->near_link_pos();
|
||||
int offset_to_next =
|
||||
static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
|
||||
ASSERT(offset_to_next <= 0);
|
||||
int disp = pos - (fixup_pos + sizeof(int8_t));
|
||||
ASSERT(is_int8(disp));
|
||||
set_byte_at(fixup_pos, disp);
|
||||
if (offset_to_next < 0) {
|
||||
L->link_to(fixup_pos + offset_to_next, Label::kNear);
|
||||
} else {
|
||||
L->UnuseNear();
|
||||
}
|
||||
}
|
||||
L->bind_to(pos);
|
||||
}
|
||||
|
||||
@ -1214,7 +1228,7 @@ void Assembler::int3() {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::j(Condition cc, Label* L) {
|
||||
void Assembler::j(Condition cc, Label* L, Hint hint, Label::Distance distance) {
|
||||
if (cc == always) {
|
||||
jmp(L);
|
||||
return;
|
||||
@ -1223,6 +1237,7 @@ void Assembler::j(Condition cc, Label* L) {
|
||||
}
|
||||
EnsureSpace ensure_space(this);
|
||||
ASSERT(is_uint4(cc));
|
||||
if (FLAG_emit_branch_hints && hint != no_hint) emit(hint);
|
||||
if (L->is_bound()) {
|
||||
const int short_size = 2;
|
||||
const int long_size = 6;
|
||||
@ -1238,6 +1253,17 @@ void Assembler::j(Condition cc, Label* L) {
|
||||
emit(0x80 | cc);
|
||||
emitl(offs - long_size);
|
||||
}
|
||||
} else if (distance == Label::kNear) {
|
||||
// 0111 tttn #8-bit disp
|
||||
emit(0x70 | cc);
|
||||
byte disp = 0x00;
|
||||
if (L->is_near_linked()) {
|
||||
int offset = L->near_link_pos() - pc_offset();
|
||||
ASSERT(is_int8(offset));
|
||||
disp = static_cast<byte>(offset & 0xFF);
|
||||
}
|
||||
L->link_to(pc_offset(), Label::kNear);
|
||||
emit(disp);
|
||||
} else if (L->is_linked()) {
|
||||
// 0000 1111 1000 tttn #32-bit disp.
|
||||
emit(0x0F);
|
||||
@ -1287,7 +1313,7 @@ void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::jmp(Label* L) {
|
||||
void Assembler::jmp(Label* L, Label::Distance distance) {
|
||||
EnsureSpace ensure_space(this);
|
||||
const int short_size = sizeof(int8_t);
|
||||
const int long_size = sizeof(int32_t);
|
||||
@ -1303,7 +1329,17 @@ void Assembler::jmp(Label* L) {
|
||||
emit(0xE9);
|
||||
emitl(offs - long_size);
|
||||
}
|
||||
} else if (L->is_linked()) {
|
||||
} else if (distance == Label::kNear) {
|
||||
emit(0xEB);
|
||||
byte disp = 0x00;
|
||||
if (L->is_near_linked()) {
|
||||
int offset = L->near_link_pos() - pc_offset();
|
||||
ASSERT(is_int8(offset));
|
||||
disp = static_cast<byte>(offset & 0xFF);
|
||||
}
|
||||
L->link_to(pc_offset(), Label::kNear);
|
||||
emit(disp);
|
||||
} else if (L->is_linked()) {
|
||||
// 1110 1001 #32-bit disp.
|
||||
emit(0xE9);
|
||||
emitl(L->pos());
|
||||
|
@ -1178,6 +1178,7 @@ class Assembler : public AssemblerBase {
|
||||
// but it may be bound only once.
|
||||
|
||||
void bind(Label* L); // binds an unbound label L to the current code position
|
||||
// DEPRECATED. Use bind(Label*) with jmp(Label*, Label::kNear) instead.
|
||||
void bind(NearLabel* L);
|
||||
|
||||
// Calls
|
||||
@ -1202,7 +1203,8 @@ class Assembler : public AssemblerBase {
|
||||
// Jumps
|
||||
// Jump short or near relative.
|
||||
// Use a 32-bit signed displacement.
|
||||
void jmp(Label* L); // unconditional jump to L
|
||||
// Unconditional jump to L
|
||||
void jmp(Label* L, Label::Distance distance = Label::kFar);
|
||||
void jmp(Handle<Code> target, RelocInfo::Mode rmode);
|
||||
|
||||
// Jump near absolute indirect (r64)
|
||||
@ -1212,13 +1214,21 @@ class Assembler : public AssemblerBase {
|
||||
void jmp(const Operand& src);
|
||||
|
||||
// Short jump
|
||||
// DEPRECATED. Use jmp(L, Label::kNear) instead.
|
||||
void jmp(NearLabel* L);
|
||||
|
||||
// Conditional jumps
|
||||
void j(Condition cc, Label* L);
|
||||
void j(Condition cc,
|
||||
Label* L,
|
||||
Hint hint,
|
||||
Label::Distance distance = Label::kFar);
|
||||
void j(Condition cc, Label* L, Label::Distance distance = Label::kFar) {
|
||||
j(cc, L, no_hint, distance);
|
||||
}
|
||||
void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
|
||||
|
||||
// Conditional short jump
|
||||
// DEPRECATED. Use jmp(L, Label::kNear) instead.
|
||||
void j(Condition cc, NearLabel* L, Hint hint = no_hint);
|
||||
|
||||
// Floating-point operations
|
||||
|
@ -576,15 +576,15 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
|
||||
__ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize));
|
||||
|
||||
// Switch on the state.
|
||||
NearLabel not_no_registers, not_tos_rax;
|
||||
Label not_no_registers, not_tos_rax;
|
||||
__ cmpq(rcx, Immediate(FullCodeGenerator::NO_REGISTERS));
|
||||
__ j(not_equal, ¬_no_registers);
|
||||
__ j(not_equal, ¬_no_registers, Label::kNear);
|
||||
__ ret(1 * kPointerSize); // Remove state.
|
||||
|
||||
__ bind(¬_no_registers);
|
||||
__ movq(rax, Operand(rsp, 2 * kPointerSize));
|
||||
__ cmpq(rcx, Immediate(FullCodeGenerator::TOS_REG));
|
||||
__ j(not_equal, ¬_tos_rax);
|
||||
__ j(not_equal, ¬_tos_rax, Label::kNear);
|
||||
__ ret(2 * kPointerSize); // Remove state, rax.
|
||||
|
||||
__ bind(¬_tos_rax);
|
||||
@ -1474,17 +1474,17 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
|
||||
|
||||
// If the result was -1 it means that we couldn't optimize the
|
||||
// function. Just return and continue in the unoptimized version.
|
||||
NearLabel skip;
|
||||
Label skip;
|
||||
__ SmiCompare(rax, Smi::FromInt(-1));
|
||||
__ j(not_equal, &skip);
|
||||
__ j(not_equal, &skip, Label::kNear);
|
||||
__ ret(0);
|
||||
|
||||
// If we decide not to perform on-stack replacement we perform a
|
||||
// stack guard check to enable interrupts.
|
||||
__ bind(&stack_check);
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
|
||||
__ j(above_equal, &ok);
|
||||
__ j(above_equal, &ok, Label::kNear);
|
||||
|
||||
StackCheckStub stub;
|
||||
__ TailCallStub(&stub);
|
||||
|
@ -40,15 +40,15 @@ namespace internal {
|
||||
|
||||
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;
|
||||
__ SmiTest(rax);
|
||||
__ j(not_zero, &check_heap_number);
|
||||
__ j(not_zero, &check_heap_number, Label::kNear);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&check_heap_number);
|
||||
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
||||
Heap::kHeapNumberMapRootIndex);
|
||||
__ j(not_equal, &call_builtin);
|
||||
__ j(not_equal, &call_builtin, Label::kNear);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&call_builtin);
|
||||
@ -232,12 +232,12 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void ToBooleanStub::Generate(MacroAssembler* masm) {
|
||||
NearLabel false_result, true_result, not_string;
|
||||
Label false_result, true_result, not_string;
|
||||
__ movq(rax, Operand(rsp, 1 * kPointerSize));
|
||||
|
||||
// 'null' => false.
|
||||
__ CompareRoot(rax, Heap::kNullValueRootIndex);
|
||||
__ j(equal, &false_result);
|
||||
__ j(equal, &false_result, Label::kNear);
|
||||
|
||||
// Get the map and type of the heap object.
|
||||
// We don't use CmpObjectType because we manipulate the type field.
|
||||
@ -247,28 +247,28 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
||||
// Undetectable => false.
|
||||
__ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset));
|
||||
__ and_(rbx, Immediate(1 << Map::kIsUndetectable));
|
||||
__ j(not_zero, &false_result);
|
||||
__ j(not_zero, &false_result, Label::kNear);
|
||||
|
||||
// JavaScript object => true.
|
||||
__ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE));
|
||||
__ j(above_equal, &true_result);
|
||||
__ j(above_equal, &true_result, Label::kNear);
|
||||
|
||||
// String value => false iff empty.
|
||||
__ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE));
|
||||
__ j(above_equal, ¬_string);
|
||||
__ j(above_equal, ¬_string, Label::kNear);
|
||||
__ movq(rdx, FieldOperand(rax, String::kLengthOffset));
|
||||
__ SmiTest(rdx);
|
||||
__ j(zero, &false_result);
|
||||
__ jmp(&true_result);
|
||||
__ j(zero, &false_result, Label::kNear);
|
||||
__ jmp(&true_result, Label::kNear);
|
||||
|
||||
__ bind(¬_string);
|
||||
__ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
|
||||
__ j(not_equal, &true_result);
|
||||
__ j(not_equal, &true_result, Label::kNear);
|
||||
// HeapNumber => false iff +0, -0, or NaN.
|
||||
// These three cases set the zero flag when compared to zero using ucomisd.
|
||||
__ xorps(xmm0, xmm0);
|
||||
__ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
|
||||
__ j(zero, &false_result);
|
||||
__ j(zero, &false_result, Label::kNear);
|
||||
// Fall through to |true_result|.
|
||||
|
||||
// Return 1/0 for true/false in rax.
|
||||
@ -334,7 +334,7 @@ void IntegerConvert(MacroAssembler* masm,
|
||||
// cvttsd2si (32-bit version) directly.
|
||||
Register double_exponent = rbx;
|
||||
Register double_value = rdi;
|
||||
NearLabel done, exponent_63_plus;
|
||||
Label done, exponent_63_plus;
|
||||
// Get double and extract exponent.
|
||||
__ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
|
||||
// Clear result preemptively, in case we need to return zero.
|
||||
@ -347,17 +347,17 @@ void IntegerConvert(MacroAssembler* masm,
|
||||
__ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
|
||||
// Check whether the exponent is too big for a 63 bit unsigned integer.
|
||||
__ cmpl(double_exponent, Immediate(63));
|
||||
__ j(above_equal, &exponent_63_plus);
|
||||
__ j(above_equal, &exponent_63_plus, Label::kNear);
|
||||
// Handle exponent range 0..62.
|
||||
__ cvttsd2siq(result, xmm0);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&exponent_63_plus);
|
||||
// Exponent negative or 63+.
|
||||
__ cmpl(double_exponent, Immediate(83));
|
||||
// If exponent negative or above 83, number contains no significant bits in
|
||||
// the range 0..2^31, so result is zero, and rcx already holds zero.
|
||||
__ j(above, &done);
|
||||
__ j(above, &done, Label::kNear);
|
||||
|
||||
// Exponent in rage 63..83.
|
||||
// Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
|
||||
@ -1157,18 +1157,18 @@ void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
// Convert oddball arguments to numbers.
|
||||
NearLabel check, done;
|
||||
Label check, done;
|
||||
__ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &check);
|
||||
__ j(not_equal, &check, Label::kNear);
|
||||
if (Token::IsBitOp(op_)) {
|
||||
__ xor_(rdx, rdx);
|
||||
} else {
|
||||
__ LoadRoot(rdx, Heap::kNanValueRootIndex);
|
||||
}
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&check);
|
||||
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
if (Token::IsBitOp(op_)) {
|
||||
__ xor_(rax, rax);
|
||||
} else {
|
||||
@ -1277,7 +1277,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
||||
const bool tagged = (argument_type_ == TAGGED);
|
||||
if (tagged) {
|
||||
NearLabel input_not_smi;
|
||||
NearLabel loaded;
|
||||
Label loaded;
|
||||
// Test that rax is a number.
|
||||
__ movq(rax, Operand(rsp, kPointerSize));
|
||||
__ JumpIfNotSmi(rax, &input_not_smi);
|
||||
@ -1291,7 +1291,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
||||
__ movq(rdx, xmm1);
|
||||
__ fld_d(Operand(rsp, 0));
|
||||
__ addq(rsp, Immediate(kDoubleSize));
|
||||
__ jmp(&loaded);
|
||||
__ jmp(&loaded, Label::kNear);
|
||||
|
||||
__ bind(&input_not_smi);
|
||||
// Check if input is a HeapNumber.
|
||||
@ -1366,9 +1366,9 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
||||
__ addl(rcx, rcx);
|
||||
__ lea(rcx, Operand(rax, rcx, times_8, 0));
|
||||
// Check if cache matches: Double value is stored in uint32_t[2] array.
|
||||
NearLabel cache_miss;
|
||||
Label cache_miss;
|
||||
__ cmpq(rbx, Operand(rcx, 0));
|
||||
__ j(not_equal, &cache_miss);
|
||||
__ j(not_equal, &cache_miss, Label::kNear);
|
||||
// Cache hit!
|
||||
__ movq(rax, Operand(rcx, 2 * kIntSize));
|
||||
if (tagged) {
|
||||
@ -1476,8 +1476,8 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
|
||||
__ j(below, &in_range);
|
||||
// Check for infinity and NaN. Both return NaN for sin.
|
||||
__ cmpl(rdi, Immediate(0x7ff));
|
||||
NearLabel non_nan_result;
|
||||
__ j(not_equal, &non_nan_result);
|
||||
Label non_nan_result;
|
||||
__ j(not_equal, &non_nan_result, Label::kNear);
|
||||
// Input is +/-Infinity or NaN. Result is NaN.
|
||||
__ fstp(0);
|
||||
__ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex);
|
||||
@ -1505,7 +1505,7 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
|
||||
|
||||
// Compute st(0) % st(1)
|
||||
{
|
||||
NearLabel partial_remainder_loop;
|
||||
Label partial_remainder_loop;
|
||||
__ bind(&partial_remainder_loop);
|
||||
__ fprem1();
|
||||
__ fwait();
|
||||
@ -1698,7 +1698,7 @@ void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm,
|
||||
|
||||
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
||||
|
||||
NearLabel first_smi, check_second;
|
||||
NearLabel first_smi;
|
||||
__ JumpIfSmi(first, &first_smi);
|
||||
__ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map);
|
||||
__ j(not_equal, on_not_smis);
|
||||
@ -1714,7 +1714,6 @@ void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm,
|
||||
__ j(not_equal, on_not_smis);
|
||||
__ Integer32ToSmi(first, smi_result);
|
||||
|
||||
__ bind(&check_second);
|
||||
__ JumpIfSmi(second, (on_success != NULL) ? on_success : &done);
|
||||
__ bind(&first_smi);
|
||||
if (FLAG_debug_code) {
|
||||
@ -1785,20 +1784,20 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
__ movq(rdx, rax);
|
||||
|
||||
// Get absolute value of exponent.
|
||||
NearLabel no_neg;
|
||||
Label no_neg;
|
||||
__ cmpl(rax, Immediate(0));
|
||||
__ j(greater_equal, &no_neg);
|
||||
__ j(greater_equal, &no_neg, Label::kNear);
|
||||
__ negl(rax);
|
||||
__ bind(&no_neg);
|
||||
|
||||
// Load xmm1 with 1.
|
||||
__ movaps(xmm1, xmm3);
|
||||
NearLabel while_true;
|
||||
NearLabel no_multiply;
|
||||
Label while_true;
|
||||
Label no_multiply;
|
||||
|
||||
__ bind(&while_true);
|
||||
__ shrl(rax, Immediate(1));
|
||||
__ j(not_carry, &no_multiply);
|
||||
__ j(not_carry, &no_multiply, Label::kNear);
|
||||
__ mulsd(xmm1, xmm0);
|
||||
__ bind(&no_multiply);
|
||||
__ mulsd(xmm0, xmm0);
|
||||
@ -1829,11 +1828,11 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
__ j(parity_even, &call_runtime);
|
||||
|
||||
NearLabel base_not_smi;
|
||||
NearLabel handle_special_cases;
|
||||
Label handle_special_cases;
|
||||
__ JumpIfNotSmi(rdx, &base_not_smi);
|
||||
__ SmiToInteger32(rdx, rdx);
|
||||
__ cvtlsi2sd(xmm0, rdx);
|
||||
__ jmp(&handle_special_cases);
|
||||
__ jmp(&handle_special_cases, Label::kNear);
|
||||
|
||||
__ bind(&base_not_smi);
|
||||
__ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
|
||||
@ -1848,14 +1847,14 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// 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.
|
||||
__ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE);
|
||||
__ movq(xmm2, rcx);
|
||||
// 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.
|
||||
@ -2174,7 +2173,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// rax: RegExp data (FixedArray)
|
||||
// Check the representation and encoding of the subject string.
|
||||
NearLabel seq_ascii_string, seq_two_byte_string, check_code;
|
||||
Label seq_ascii_string, seq_two_byte_string, check_code;
|
||||
__ movq(rdi, Operand(rsp, kSubjectOffset));
|
||||
__ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||
@ -2182,10 +2181,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ andb(rbx, Immediate(
|
||||
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask));
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string);
|
||||
__ j(zero, &seq_two_byte_string, Label::kNear);
|
||||
// Any other flat string must be a flat ascii string.
|
||||
__ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask));
|
||||
__ j(zero, &seq_ascii_string);
|
||||
__ j(zero, &seq_ascii_string, Label::kNear);
|
||||
|
||||
// Check for flat cons string.
|
||||
// A flat cons string is a cons string where the second part is the empty
|
||||
@ -2209,7 +2208,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
|
||||
Immediate(kStringRepresentationMask | kStringEncodingMask));
|
||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string);
|
||||
__ j(zero, &seq_two_byte_string, Label::kNear);
|
||||
// Any other flat string must be ascii.
|
||||
__ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
|
||||
Immediate(kStringRepresentationMask));
|
||||
@ -2220,7 +2219,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// rax: RegExp data (FixedArray)
|
||||
__ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
|
||||
__ Set(rcx, 1); // Type is ascii.
|
||||
__ jmp(&check_code);
|
||||
__ jmp(&check_code, Label::kNear);
|
||||
|
||||
__ bind(&seq_two_byte_string);
|
||||
// rdi: subject string (flat two-byte)
|
||||
@ -2306,13 +2305,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Argument 4: End of string data
|
||||
// Argument 3: Start of string data
|
||||
NearLabel setup_two_byte, setup_rest;
|
||||
Label setup_two_byte, setup_rest;
|
||||
__ testb(rcx, rcx); // Last use of rcx as encoding of subject string.
|
||||
__ j(zero, &setup_two_byte);
|
||||
__ j(zero, &setup_two_byte, Label::kNear);
|
||||
__ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
|
||||
__ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize));
|
||||
__ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
|
||||
__ jmp(&setup_rest);
|
||||
__ jmp(&setup_rest, Label::kNear);
|
||||
__ bind(&setup_two_byte);
|
||||
__ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
|
||||
__ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize));
|
||||
@ -2337,10 +2336,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ LeaveApiExitFrame();
|
||||
|
||||
// Check the result.
|
||||
NearLabel success;
|
||||
Label success;
|
||||
Label exception;
|
||||
__ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
|
||||
__ j(equal, &success);
|
||||
__ j(equal, &success, Label::kNear);
|
||||
__ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
|
||||
__ j(equal, &exception);
|
||||
__ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
|
||||
@ -2389,12 +2388,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// rbx: last_match_info backing store (FixedArray)
|
||||
// rcx: offsets vector
|
||||
// rdx: 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);
|
||||
__ subq(rdx, Immediate(1));
|
||||
__ j(negative, &done);
|
||||
__ j(negative, &done, Label::kNear);
|
||||
// Read the value from the static offsets vector buffer and make it a smi.
|
||||
__ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
|
||||
__ Integer32ToSmi(rdi, rdi);
|
||||
@ -2427,8 +2426,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ movq(pending_exception_operand, rdx);
|
||||
|
||||
__ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
|
||||
NearLabel termination_exception;
|
||||
__ j(equal, &termination_exception);
|
||||
Label termination_exception;
|
||||
__ j(equal, &termination_exception, Label::kNear);
|
||||
__ Throw(rax);
|
||||
|
||||
__ bind(&termination_exception);
|
||||
@ -2671,16 +2670,16 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Two identical objects are equal unless they are both NaN or undefined.
|
||||
{
|
||||
NearLabel not_identical;
|
||||
Label not_identical;
|
||||
__ cmpq(rax, rdx);
|
||||
__ j(not_equal, ¬_identical);
|
||||
__ j(not_equal, ¬_identical, Label::kNear);
|
||||
|
||||
if (cc_ != equal) {
|
||||
// Check for undefined. undefined OP undefined is false even though
|
||||
// undefined == undefined.
|
||||
NearLabel check_for_nan;
|
||||
Label check_for_nan;
|
||||
__ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &check_for_nan);
|
||||
__ j(not_equal, &check_for_nan, Label::kNear);
|
||||
__ Set(rax, NegativeComparisonResult(cc_));
|
||||
__ ret(0);
|
||||
__ bind(&check_for_nan);
|
||||
@ -2695,15 +2694,15 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
__ Set(rax, EQUAL);
|
||||
__ ret(0);
|
||||
} else {
|
||||
NearLabel heap_number;
|
||||
Label heap_number;
|
||||
// If it's not a heap number, then return equal for (in)equality operator.
|
||||
__ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
|
||||
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(rax, FIRST_JS_OBJECT_TYPE, rcx);
|
||||
__ j(above_equal, ¬_identical);
|
||||
__ j(above_equal, ¬_identical, Label::kNear);
|
||||
}
|
||||
__ Set(rax, EQUAL);
|
||||
__ ret(0);
|
||||
@ -2759,9 +2758,9 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// If the first object is a JS object, we have done pointer comparison.
|
||||
STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
||||
NearLabel first_non_object;
|
||||
Label first_non_object;
|
||||
__ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
|
||||
__ j(below, &first_non_object);
|
||||
__ j(below, &first_non_object, Label::kNear);
|
||||
// Return non-zero (eax (not rax) is not zero)
|
||||
Label return_not_equal;
|
||||
STATIC_ASSERT(kHeapObjectTag != 0);
|
||||
@ -2788,14 +2787,14 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
// Generate the number comparison code.
|
||||
if (include_number_compare_) {
|
||||
Label non_number_comparison;
|
||||
NearLabel unordered;
|
||||
Label unordered;
|
||||
FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
|
||||
__ xorl(rax, rax);
|
||||
__ xorl(rcx, rcx);
|
||||
__ ucomisd(xmm0, xmm1);
|
||||
|
||||
// Don't base result on EFLAGS when a NaN is involved.
|
||||
__ j(parity_even, &unordered);
|
||||
__ j(parity_even, &unordered, Label::kNear);
|
||||
// Return a result of -1, 0, or 1, based on EFLAGS.
|
||||
__ setcc(above, rax);
|
||||
__ setcc(below, rcx);
|
||||
@ -2860,7 +2859,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
// Not strict equality. Objects are unequal if
|
||||
// they are both JSObjects and not undetectable,
|
||||
// and their pointers are different.
|
||||
NearLabel not_both_objects, return_unequal;
|
||||
Label not_both_objects, 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.
|
||||
@ -2868,17 +2867,17 @@ void CompareStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kSmiTagMask == 1);
|
||||
__ lea(rcx, Operand(rax, rdx, times_1, 0));
|
||||
__ testb(rcx, Immediate(kSmiTagMask));
|
||||
__ j(not_zero, ¬_both_objects);
|
||||
__ j(not_zero, ¬_both_objects, Label::kNear);
|
||||
__ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
|
||||
__ j(below, ¬_both_objects);
|
||||
__ j(below, ¬_both_objects, Label::kNear);
|
||||
__ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx);
|
||||
__ j(below, ¬_both_objects);
|
||||
__ j(below, ¬_both_objects, Label::kNear);
|
||||
__ testb(FieldOperand(rbx, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
__ j(zero, &return_unequal);
|
||||
__ j(zero, &return_unequal, Label::kNear);
|
||||
__ testb(FieldOperand(rcx, Map::kBitFieldOffset),
|
||||
Immediate(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(rax, EQUAL);
|
||||
@ -3108,11 +3107,11 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
||||
// Handling of failure.
|
||||
__ bind(&failure_returned);
|
||||
|
||||
NearLabel retry;
|
||||
Label retry;
|
||||
// If the returned exception is RETRY_AFTER_GC continue at retry label
|
||||
STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
|
||||
__ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
|
||||
__ j(zero, &retry);
|
||||
__ j(zero, &retry, Label::kNear);
|
||||
|
||||
// Special handling of out of memory exceptions.
|
||||
__ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
|
||||
@ -3413,11 +3412,11 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
||||
// 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;
|
||||
__ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
|
||||
__ j(not_equal, &miss);
|
||||
__ j(not_equal, &miss, Label::kNear);
|
||||
__ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
|
||||
__ j(not_equal, &miss);
|
||||
__ j(not_equal, &miss, Label::kNear);
|
||||
__ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
|
||||
__ ret(2 * kPointerSize);
|
||||
__ bind(&miss);
|
||||
@ -3453,15 +3452,15 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
||||
__ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
|
||||
|
||||
// Loop through the prototype chain looking for the function prototype.
|
||||
NearLabel loop, is_instance, is_not_instance;
|
||||
Label loop, is_instance, is_not_instance;
|
||||
__ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
|
||||
__ bind(&loop);
|
||||
__ cmpq(rcx, rbx);
|
||||
__ j(equal, &is_instance);
|
||||
__ j(equal, &is_instance, Label::kNear);
|
||||
__ cmpq(rcx, kScratchRegister);
|
||||
// The code at is_not_instance assumes that kScratchRegister contains a
|
||||
// non-zero GCable value (the null object in this case).
|
||||
__ j(equal, &is_not_instance);
|
||||
__ j(equal, &is_not_instance, Label::kNear);
|
||||
__ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
|
||||
__ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
|
||||
__ jmp(&loop);
|
||||
@ -3826,10 +3825,10 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// rax: first string
|
||||
// rdx: 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;
|
||||
__ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
|
||||
__ SmiTest(rcx);
|
||||
__ 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 rax.
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
@ -3837,7 +3836,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ bind(&second_not_zero_length);
|
||||
__ movq(rbx, FieldOperand(rax, String::kLengthOffset));
|
||||
__ SmiTest(rbx);
|
||||
__ 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 rdx.
|
||||
__ movq(rax, rdx);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
@ -4131,9 +4130,9 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
|
||||
ASSERT(count.is(rcx)); // rep movs count
|
||||
|
||||
// Nothing to do for zero characters.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ testl(count, count);
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
|
||||
// Make count the number of bytes to copy.
|
||||
if (!ascii) {
|
||||
@ -4142,9 +4141,9 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Don't enter the rep movs if there are less than 4 bytes to copy.
|
||||
NearLabel last_bytes;
|
||||
Label last_bytes;
|
||||
__ testl(count, Immediate(~7));
|
||||
__ j(zero, &last_bytes);
|
||||
__ j(zero, &last_bytes, Label::kNear);
|
||||
|
||||
// Copy from edi to esi using rep movs instruction.
|
||||
__ movl(kScratchRegister, count);
|
||||
@ -4158,7 +4157,7 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
|
||||
// Check if there are more bytes to copy.
|
||||
__ bind(&last_bytes);
|
||||
__ testl(count, count);
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
|
||||
// Copy remaining characters.
|
||||
Label loop;
|
||||
@ -4186,10 +4185,10 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// 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;
|
||||
__ leal(scratch, Operand(c1, -'0'));
|
||||
__ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
|
||||
__ j(above, ¬_array_index);
|
||||
__ j(above, ¬_array_index, Label::kNear);
|
||||
__ leal(scratch, Operand(c2, -'0'));
|
||||
__ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
|
||||
__ j(below_equal, not_found);
|
||||
@ -4251,9 +4250,9 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
SymbolTable::kElementsStartOffset));
|
||||
|
||||
// If entry is undefined no string with this hash can be found.
|
||||
NearLabel is_string;
|
||||
Label is_string;
|
||||
__ CmpObjectType(candidate, ODDBALL_TYPE, map);
|
||||
__ j(not_equal, &is_string);
|
||||
__ j(not_equal, &is_string, Label::kNear);
|
||||
|
||||
__ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, not_found);
|
||||
@ -4505,19 +4504,19 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
|
||||
Register length = scratch1;
|
||||
|
||||
// Compare lengths.
|
||||
NearLabel check_zero_length;
|
||||
Label check_zero_length;
|
||||
__ movq(length, FieldOperand(left, String::kLengthOffset));
|
||||
__ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
|
||||
__ j(equal, &check_zero_length);
|
||||
__ j(equal, &check_zero_length, Label::kNear);
|
||||
__ Move(rax, Smi::FromInt(NOT_EQUAL));
|
||||
__ ret(0);
|
||||
|
||||
// Check if the length is zero.
|
||||
NearLabel compare_chars;
|
||||
Label compare_chars;
|
||||
__ bind(&check_zero_length);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ SmiTest(length);
|
||||
__ j(not_zero, &compare_chars);
|
||||
__ j(not_zero, &compare_chars, Label::kNear);
|
||||
__ Move(rax, Smi::FromInt(EQUAL));
|
||||
__ ret(0);
|
||||
|
||||
@ -4557,8 +4556,8 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
|
||||
FieldOperand(right, String::kLengthOffset));
|
||||
// Register scratch4 now holds left.length - right.length.
|
||||
const Register length_difference = scratch4;
|
||||
NearLabel left_shorter;
|
||||
__ j(less, &left_shorter);
|
||||
Label left_shorter;
|
||||
__ j(less, &left_shorter, Label::kNear);
|
||||
// The right string isn't longer that the left one.
|
||||
// Get the right string's length by subtracting the (non-negative) difference
|
||||
// from the left string's length.
|
||||
@ -4567,10 +4566,10 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
|
||||
// Register scratch1 now holds Min(left.length, right.length).
|
||||
const Register min_length = scratch1;
|
||||
|
||||
NearLabel compare_lengths;
|
||||
Label compare_lengths;
|
||||
// If min-length is zero, go directly to comparing lengths.
|
||||
__ SmiTest(min_length);
|
||||
__ j(zero, &compare_lengths);
|
||||
__ j(zero, &compare_lengths, Label::kNear);
|
||||
|
||||
// Compare loop.
|
||||
NearLabel result_not_equal;
|
||||
@ -4581,16 +4580,16 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
|
||||
// Compare lengths (precomputed).
|
||||
__ bind(&compare_lengths);
|
||||
__ SmiTest(length_difference);
|
||||
__ j(not_zero, &result_not_equal);
|
||||
__ j(not_zero, &result_not_equal, Label::kNear);
|
||||
|
||||
// Result is EQUAL.
|
||||
__ Move(rax, Smi::FromInt(EQUAL));
|
||||
__ ret(0);
|
||||
|
||||
NearLabel result_greater;
|
||||
Label result_greater;
|
||||
__ bind(&result_not_equal);
|
||||
// Unequal comparison of left to right, either character or length.
|
||||
__ j(greater, &result_greater);
|
||||
__ j(greater, &result_greater, Label::kNear);
|
||||
|
||||
// Result is LESS.
|
||||
__ Move(rax, Smi::FromInt(LESS));
|
||||
@ -4622,7 +4621,7 @@ void StringCompareStub::GenerateAsciiCharsCompareLoop(
|
||||
Register index = length; // index = -length;
|
||||
|
||||
// Compare loop.
|
||||
NearLabel loop;
|
||||
Label loop;
|
||||
__ bind(&loop);
|
||||
__ movb(scratch, Operand(left, index, times_1, 0));
|
||||
__ cmpb(scratch, Operand(right, index, times_1, 0));
|
||||
@ -4644,9 +4643,9 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
|
||||
__ movq(rax, Operand(rsp, 1 * kPointerSize)); // right
|
||||
|
||||
// Check for identity.
|
||||
NearLabel not_same;
|
||||
Label not_same;
|
||||
__ cmpq(rdx, rax);
|
||||
__ j(not_equal, ¬_same);
|
||||
__ j(not_equal, ¬_same, Label::kNear);
|
||||
__ Move(rax, Smi::FromInt(EQUAL));
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->string_compare_native(), 1);
|
||||
@ -4681,9 +4680,9 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
||||
// For equality we do not care about the sign of the result.
|
||||
__ subq(rax, rdx);
|
||||
} else {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ subq(rdx, rax);
|
||||
__ j(no_overflow, &done);
|
||||
__ j(no_overflow, &done, Label::kNear);
|
||||
// Correct sign of result in case of overflow.
|
||||
__ SmiNot(rdx, rdx);
|
||||
__ bind(&done);
|
||||
@ -4699,16 +4698,16 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
|
||||
void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::HEAP_NUMBERS);
|
||||
|
||||
NearLabel generic_stub;
|
||||
NearLabel unordered;
|
||||
NearLabel miss;
|
||||
Label generic_stub;
|
||||
Label unordered;
|
||||
Label miss;
|
||||
Condition either_smi = masm->CheckEitherSmi(rax, rdx);
|
||||
__ j(either_smi, &generic_stub);
|
||||
__ j(either_smi, &generic_stub, Label::kNear);
|
||||
|
||||
__ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx);
|
||||
__ j(not_equal, &miss);
|
||||
__ j(not_equal, &miss, Label::kNear);
|
||||
__ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
|
||||
__ j(not_equal, &miss);
|
||||
__ j(not_equal, &miss, Label::kNear);
|
||||
|
||||
// Load left and right operand
|
||||
__ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
|
||||
@ -4718,7 +4717,7 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
|
||||
__ ucomisd(xmm0, xmm1);
|
||||
|
||||
// Don't base result on EFLAGS when a NaN is involved.
|
||||
__ j(parity_even, &unordered);
|
||||
__ 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.
|
||||
@ -4750,9 +4749,9 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
Register tmp2 = rbx;
|
||||
|
||||
// Check that both operands are heap objects.
|
||||
NearLabel miss;
|
||||
Label miss;
|
||||
Condition cond = masm->CheckEitherSmi(left, right, tmp1);
|
||||
__ j(cond, &miss);
|
||||
__ j(cond, &miss, Label::kNear);
|
||||
|
||||
// Check that both operands are symbols.
|
||||
__ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
|
||||
@ -4762,15 +4761,15 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ testb(tmp1, Immediate(kIsSymbolMask));
|
||||
__ j(zero, &miss);
|
||||
__ j(zero, &miss, Label::kNear);
|
||||
|
||||
// Symbols are compared by identity.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ cmpq(left, right);
|
||||
// Make sure rax is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
ASSERT(right.is(rax));
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ Move(rax, Smi::FromInt(EQUAL));
|
||||
@ -4811,9 +4810,9 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
__ j(not_zero, &miss);
|
||||
|
||||
// Fast check for identical strings.
|
||||
NearLabel not_same;
|
||||
Label not_same;
|
||||
__ cmpq(left, right);
|
||||
__ j(not_equal, ¬_same);
|
||||
__ j(not_equal, ¬_same, Label::kNear);
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ Move(rax, Smi::FromInt(EQUAL));
|
||||
@ -4824,11 +4823,11 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
|
||||
// Check that both strings are symbols. If they are, we're done
|
||||
// because we already know they are not identical.
|
||||
NearLabel do_compare;
|
||||
Label do_compare;
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ testb(tmp1, Immediate(kIsSymbolMask));
|
||||
__ j(zero, &do_compare);
|
||||
__ j(zero, &do_compare, Label::kNear);
|
||||
// Make sure rax is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
ASSERT(right.is(rax));
|
||||
@ -4858,14 +4857,14 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
|
||||
void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::OBJECTS);
|
||||
NearLabel miss;
|
||||
Label miss;
|
||||
Condition either_smi = masm->CheckEitherSmi(rdx, rax);
|
||||
__ j(either_smi, &miss);
|
||||
__ j(either_smi, &miss, Label::kNear);
|
||||
|
||||
__ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
|
||||
__ j(not_equal, &miss, not_taken);
|
||||
__ j(not_equal, &miss, not_taken, Label::kNear);
|
||||
__ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
|
||||
__ j(not_equal, &miss, not_taken);
|
||||
__ j(not_equal, &miss, not_taken, Label::kNear);
|
||||
|
||||
ASSERT(GetCondition() == equal);
|
||||
__ subq(rax, rdx);
|
||||
|
@ -239,9 +239,9 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
|
||||
|
||||
{ Comment cmnt(masm_, "[ Stack check");
|
||||
PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
|
||||
__ j(above_equal, &ok);
|
||||
__ j(above_equal, &ok, Label::kNear);
|
||||
StackCheckStub stub;
|
||||
__ CallStub(&stub);
|
||||
__ bind(&ok);
|
||||
@ -270,9 +270,9 @@ void FullCodeGenerator::ClearAccumulator() {
|
||||
|
||||
void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ Stack check");
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
|
||||
__ j(above_equal, &ok);
|
||||
__ j(above_equal, &ok, Label::kNear);
|
||||
StackCheckStub stub;
|
||||
__ CallStub(&stub);
|
||||
// Record a mapping of this PC offset to the OSR id. This is used to find
|
||||
@ -485,10 +485,10 @@ void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
|
||||
void FullCodeGenerator::AccumulatorValueContext::Plug(
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) const {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ bind(materialize_true);
|
||||
__ Move(result_register(), isolate()->factory()->true_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(materialize_false);
|
||||
__ Move(result_register(), isolate()->factory()->false_value());
|
||||
__ bind(&done);
|
||||
@ -498,10 +498,10 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(
|
||||
void FullCodeGenerator::StackValueContext::Plug(
|
||||
Label* materialize_true,
|
||||
Label* materialize_false) const {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ bind(materialize_true);
|
||||
__ Push(isolate()->factory()->true_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(materialize_false);
|
||||
__ Push(isolate()->factory()->false_value());
|
||||
__ bind(&done);
|
||||
@ -638,8 +638,8 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
||||
// preparation to avoid preparing with the same AST id twice.
|
||||
if (!context()->IsTest() || !info_->IsOptimizable()) return;
|
||||
|
||||
NearLabel skip;
|
||||
if (should_normalize) __ jmp(&skip);
|
||||
Label skip;
|
||||
if (should_normalize) __ jmp(&skip, Label::kNear);
|
||||
|
||||
ForwardBailoutStack* current = forward_bailout_stack_;
|
||||
while (current != NULL) {
|
||||
@ -918,9 +918,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ JumpIfSmi(rdx, &call_runtime);
|
||||
|
||||
// For all objects but the receiver, check that the cache is empty.
|
||||
NearLabel check_prototype;
|
||||
Label check_prototype;
|
||||
__ cmpq(rcx, rax);
|
||||
__ j(equal, &check_prototype);
|
||||
__ j(equal, &check_prototype, Label::kNear);
|
||||
__ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
||||
__ cmpq(rdx, empty_fixed_array_value);
|
||||
__ j(not_equal, &call_runtime);
|
||||
@ -933,9 +933,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// The enum cache is valid. Load the map of the object being
|
||||
// iterated over and use the cache for the iteration.
|
||||
NearLabel use_cache;
|
||||
Label use_cache;
|
||||
__ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
|
||||
__ jmp(&use_cache);
|
||||
__ jmp(&use_cache, Label::kNear);
|
||||
|
||||
// Get the set of properties to enumerate.
|
||||
__ bind(&call_runtime);
|
||||
@ -945,10 +945,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// If we got a map from the runtime call, we can do a fast
|
||||
// modification check. Otherwise, we got a fixed array, and we have
|
||||
// to do a slow check.
|
||||
NearLabel fixed_array;
|
||||
Label fixed_array;
|
||||
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
||||
Heap::kMetaMapRootIndex);
|
||||
__ j(not_equal, &fixed_array);
|
||||
__ j(not_equal, &fixed_array, Label::kNear);
|
||||
|
||||
// We got a map in register rax. Get the enumeration cache from it.
|
||||
__ bind(&use_cache);
|
||||
@ -992,10 +992,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Check if the expected map still matches that of the enumerable.
|
||||
// If not, we have to filter the key.
|
||||
NearLabel update_each;
|
||||
Label update_each;
|
||||
__ movq(rcx, Operand(rsp, 4 * kPointerSize));
|
||||
__ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
|
||||
__ j(equal, &update_each);
|
||||
__ j(equal, &update_each, Label::kNear);
|
||||
|
||||
// Convert the entry to a string or null if it isn't a property
|
||||
// anymore. If the property has been removed while iterating, we
|
||||
@ -1103,7 +1103,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
|
||||
if (s != NULL && s->is_eval_scope()) {
|
||||
// Loop up the context chain. There is no frame effect so it is
|
||||
// safe to use raw labels here.
|
||||
NearLabel next, fast;
|
||||
Label next, fast;
|
||||
if (!context.is(temp)) {
|
||||
__ movq(temp, context);
|
||||
}
|
||||
@ -1112,7 +1112,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
|
||||
__ bind(&next);
|
||||
// Terminate at global context.
|
||||
__ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
|
||||
__ j(equal, &fast);
|
||||
__ j(equal, &fast, Label::kNear);
|
||||
// Check that extension is NULL.
|
||||
__ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
|
||||
__ j(not_equal, slow);
|
||||
@ -1261,11 +1261,11 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
|
||||
if (var->mode() == Variable::CONST) {
|
||||
// Constants may be the hole value if they have not been initialized.
|
||||
// Unhole them.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
MemOperand slot_operand = EmitSlotSearch(slot, rax);
|
||||
__ movq(rax, slot_operand);
|
||||
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
__ bind(&done);
|
||||
context()->Plug(rax);
|
||||
@ -1671,7 +1671,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
// Do combined smi check of the operands. Left operand is on the
|
||||
// stack (popped into rdx). Right operand is in rax but moved into
|
||||
// rcx to make the shifts easier.
|
||||
NearLabel done, stub_call, smi_case;
|
||||
NearLabel stub_call, smi_case;
|
||||
Label done;
|
||||
__ pop(rdx);
|
||||
__ movq(rcx, rax);
|
||||
__ or_(rax, rdx);
|
||||
@ -1682,7 +1683,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
||||
__ movq(rax, rcx);
|
||||
TypeRecordingBinaryOpStub stub(op, mode);
|
||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&smi_case);
|
||||
switch (op) {
|
||||
@ -2197,8 +2198,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
NearLabel call;
|
||||
__ jmp(&call);
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(rax);
|
||||
@ -2639,7 +2640,7 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
||||
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 0);
|
||||
|
||||
NearLabel exit;
|
||||
Label exit;
|
||||
// Get the number of formal parameters.
|
||||
__ Move(rax, Smi::FromInt(scope()->num_parameters()));
|
||||
|
||||
@ -2647,7 +2648,7 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
||||
__ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ j(not_equal, &exit);
|
||||
__ j(not_equal, &exit, Label::kNear);
|
||||
|
||||
// Arguments adaptor case: Read the arguments length from the
|
||||
// adaptor frame.
|
||||
@ -3183,7 +3184,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
||||
__ movq(cache,
|
||||
FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
|
||||
|
||||
NearLabel done, not_found;
|
||||
Label done, not_found;
|
||||
// tmp now holds finger offset as a smi.
|
||||
ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
||||
__ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
|
||||
@ -3193,12 +3194,12 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
||||
index.reg,
|
||||
index.scale,
|
||||
FixedArray::kHeaderSize));
|
||||
__ j(not_equal, ¬_found);
|
||||
__ j(not_equal, ¬_found, Label::kNear);
|
||||
__ movq(rax, FieldOperand(cache,
|
||||
index.reg,
|
||||
index.scale,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(¬_found);
|
||||
// Call runtime to perform the lookup.
|
||||
@ -3222,25 +3223,25 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
||||
VisitForAccumulatorValue(args->at(1));
|
||||
__ pop(left);
|
||||
|
||||
NearLabel done, fail, ok;
|
||||
Label done, fail, ok;
|
||||
__ cmpq(left, right);
|
||||
__ j(equal, &ok);
|
||||
__ j(equal, &ok, Label::kNear);
|
||||
// Fail if either is a non-HeapObject.
|
||||
Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
|
||||
__ j(either_smi, &fail);
|
||||
__ j(zero, &fail);
|
||||
__ j(either_smi, &fail, Label::kNear);
|
||||
__ j(zero, &fail, Label::kNear);
|
||||
__ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
|
||||
__ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
|
||||
Immediate(JS_REGEXP_TYPE));
|
||||
__ j(not_equal, &fail);
|
||||
__ j(not_equal, &fail, Label::kNear);
|
||||
__ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
|
||||
__ j(not_equal, &fail);
|
||||
__ j(not_equal, &fail, Label::kNear);
|
||||
__ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
|
||||
__ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
|
||||
__ j(equal, &ok);
|
||||
__ j(equal, &ok, Label::kNear);
|
||||
__ bind(&fail);
|
||||
__ Move(rax, isolate()->factory()->false_value());
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&ok);
|
||||
__ Move(rax, isolate()->factory()->true_value());
|
||||
__ bind(&done);
|
||||
@ -3808,10 +3809,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
// Call ToNumber only if operand is not a smi.
|
||||
NearLabel no_conversion;
|
||||
Label no_conversion;
|
||||
Condition is_smi;
|
||||
is_smi = masm_->CheckSmi(rax);
|
||||
__ j(is_smi, &no_conversion);
|
||||
__ j(is_smi, &no_conversion, Label::kNear);
|
||||
ToNumberStub convert_stub;
|
||||
__ CallStub(&convert_stub);
|
||||
__ bind(&no_conversion);
|
||||
@ -3837,7 +3838,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
// Inline smi case if we are in a loop.
|
||||
NearLabel stub_call, done;
|
||||
NearLabel done;
|
||||
Label stub_call;
|
||||
JumpPatchSite patch_site(masm_);
|
||||
|
||||
if (ShouldInlineSmiCase(expr->op())) {
|
||||
@ -3846,7 +3848,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
} else {
|
||||
__ SmiSubConstant(rax, rax, Smi::FromInt(1));
|
||||
}
|
||||
__ j(overflow, &stub_call);
|
||||
__ j(overflow, &stub_call, Label::kNear);
|
||||
// We could eliminate this smi check if we split the code at
|
||||
// the first smi check before calling ToNumber.
|
||||
patch_site.EmitJumpIfSmi(rax, &done);
|
||||
|
@ -785,21 +785,21 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
|
||||
if (divisor < 0) divisor = -divisor;
|
||||
|
||||
NearLabel positive_dividend, done;
|
||||
Label positive_dividend, done;
|
||||
__ testl(dividend, dividend);
|
||||
__ j(not_sign, &positive_dividend);
|
||||
__ j(not_sign, &positive_dividend, Label::kNear);
|
||||
__ negl(dividend);
|
||||
__ andl(dividend, Immediate(divisor - 1));
|
||||
__ negl(dividend);
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
}
|
||||
__ bind(&positive_dividend);
|
||||
__ andl(dividend, Immediate(divisor - 1));
|
||||
__ bind(&done);
|
||||
} else {
|
||||
NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Register left_reg = ToRegister(instr->InputAt(0));
|
||||
Register right_reg = ToRegister(instr->InputAt(1));
|
||||
Register result_reg = ToRegister(instr->result());
|
||||
@ -816,11 +816,11 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
}
|
||||
|
||||
__ testl(left_reg, left_reg);
|
||||
__ j(zero, &remainder_eq_dividend);
|
||||
__ j(sign, &slow);
|
||||
__ j(zero, &remainder_eq_dividend, Label::kNear);
|
||||
__ j(sign, &slow, Label::kNear);
|
||||
|
||||
__ testl(right_reg, right_reg);
|
||||
__ j(not_sign, &both_positive);
|
||||
__ j(not_sign, &both_positive, Label::kNear);
|
||||
// The sign of the divisor doesn't matter.
|
||||
__ neg(right_reg);
|
||||
|
||||
@ -828,16 +828,16 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
// If the dividend is smaller than the nonnegative
|
||||
// divisor, the dividend is the result.
|
||||
__ cmpl(left_reg, right_reg);
|
||||
__ j(less, &remainder_eq_dividend);
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
|
||||
// Check if the divisor is a PowerOfTwo integer.
|
||||
Register scratch = ToRegister(instr->TempAt(0));
|
||||
__ movl(scratch, right_reg);
|
||||
__ subl(scratch, Immediate(1));
|
||||
__ testl(scratch, right_reg);
|
||||
__ j(not_zero, &do_subtraction);
|
||||
__ j(not_zero, &do_subtraction, Label::kNear);
|
||||
__ andl(left_reg, scratch);
|
||||
__ jmp(&remainder_eq_dividend);
|
||||
__ jmp(&remainder_eq_dividend, Label::kNear);
|
||||
|
||||
__ bind(&do_subtraction);
|
||||
const int kUnfolds = 3;
|
||||
@ -848,7 +848,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ subl(left_reg, right_reg);
|
||||
// Check if the dividend is less than the divisor.
|
||||
__ cmpl(left_reg, right_reg);
|
||||
__ j(less, &remainder_eq_dividend);
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
}
|
||||
__ movl(left_reg, scratch);
|
||||
|
||||
@ -860,15 +860,15 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
|
||||
// Check for (0 % -x) that will produce negative zero.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel positive_left;
|
||||
NearLabel done;
|
||||
Label positive_left;
|
||||
Label done;
|
||||
__ testl(left_reg, left_reg);
|
||||
__ j(not_sign, &positive_left);
|
||||
__ j(not_sign, &positive_left, Label::kNear);
|
||||
__ idivl(right_reg);
|
||||
|
||||
// Test the remainder for 0, because then the result would be -0.
|
||||
__ testl(result_reg, result_reg);
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
__ bind(&positive_left);
|
||||
@ -877,7 +877,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
} else {
|
||||
__ idivl(right_reg);
|
||||
}
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&remainder_eq_dividend);
|
||||
__ movl(result_reg, left_reg);
|
||||
@ -905,9 +905,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
||||
|
||||
// Check for (0 / -x) that will produce negative zero.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel left_not_zero;
|
||||
Label left_not_zero;
|
||||
__ testl(left_reg, left_reg);
|
||||
__ j(not_zero, &left_not_zero);
|
||||
__ j(not_zero, &left_not_zero, Label::kNear);
|
||||
__ testl(right_reg, right_reg);
|
||||
DeoptimizeIf(sign, instr->environment());
|
||||
__ bind(&left_not_zero);
|
||||
@ -915,9 +915,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
||||
|
||||
// Check for (-kMinInt / -1).
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
|
||||
NearLabel left_not_min_int;
|
||||
Label left_not_min_int;
|
||||
__ cmpl(left_reg, Immediate(kMinInt));
|
||||
__ j(not_zero, &left_not_min_int);
|
||||
__ j(not_zero, &left_not_min_int, Label::kNear);
|
||||
__ cmpl(right_reg, Immediate(-1));
|
||||
DeoptimizeIf(zero, instr->environment());
|
||||
__ bind(&left_not_min_int);
|
||||
@ -996,9 +996,9 @@ void LCodeGen::DoMulI(LMulI* instr) {
|
||||
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
// Bail out if the result is supposed to be negative zero.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ testl(left, left);
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
if (right->IsConstantOperand()) {
|
||||
if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
@ -1367,10 +1367,10 @@ void LCodeGen::DoBranch(LBranch* instr) {
|
||||
__ JumpIfSmi(reg, true_label);
|
||||
|
||||
// Test for double values. Plus/minus zero and NaN are false.
|
||||
NearLabel call_stub;
|
||||
Label call_stub;
|
||||
__ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
|
||||
Heap::kHeapNumberMapRootIndex);
|
||||
__ j(not_equal, &call_stub);
|
||||
__ j(not_equal, &call_stub, Label::kNear);
|
||||
|
||||
// HeapNumber => false iff +0, -0, or NaN. These three cases set the
|
||||
// zero flag when compared to zero using ucomisd.
|
||||
@ -1484,20 +1484,20 @@ void LCodeGen::DoCmpID(LCmpID* instr) {
|
||||
LOperand* right = instr->InputAt(1);
|
||||
LOperand* result = instr->result();
|
||||
|
||||
NearLabel unordered;
|
||||
Label unordered;
|
||||
if (instr->is_double()) {
|
||||
// Don't base result on EFLAGS when a NaN is involved. Instead
|
||||
// jump to the unordered case, which produces a false value.
|
||||
__ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
|
||||
__ j(parity_even, &unordered);
|
||||
__ j(parity_even, &unordered, Label::kNear);
|
||||
} else {
|
||||
EmitCmpI(left, right);
|
||||
}
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
||||
__ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex);
|
||||
__ j(cc, &done);
|
||||
__ j(cc, &done, Label::kNear);
|
||||
|
||||
__ bind(&unordered);
|
||||
__ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex);
|
||||
@ -1530,11 +1530,11 @@ void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
|
||||
Register right = ToRegister(instr->InputAt(1));
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
NearLabel different, done;
|
||||
Label different, done;
|
||||
__ cmpq(left, right);
|
||||
__ j(not_equal, &different);
|
||||
__ j(not_equal, &different, Label::kNear);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&different);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ bind(&done);
|
||||
@ -1568,16 +1568,17 @@ void LCodeGen::DoIsNull(LIsNull* instr) {
|
||||
if (instr->is_strict()) {
|
||||
ASSERT(Heap::kTrueValueRootIndex >= 0);
|
||||
__ movl(result, Immediate(Heap::kTrueValueRootIndex));
|
||||
NearLabel load;
|
||||
__ j(equal, &load);
|
||||
Label load;
|
||||
__ j(equal, &load, Label::kNear);
|
||||
__ Set(result, Heap::kFalseValueRootIndex);
|
||||
__ bind(&load);
|
||||
__ LoadRootIndexed(result, result, 0);
|
||||
} else {
|
||||
NearLabel true_value, false_value, done;
|
||||
__ j(equal, &true_value);
|
||||
NearLabel false_value;
|
||||
Label true_value, done;
|
||||
__ j(equal, &true_value, Label::kNear);
|
||||
__ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, &true_value);
|
||||
__ j(equal, &true_value, Label::kNear);
|
||||
__ JumpIfSmi(reg, &false_value);
|
||||
// Check for undetectable objects by looking in the bit field in
|
||||
// the map. The object has already been smi checked.
|
||||
@ -1585,10 +1586,10 @@ void LCodeGen::DoIsNull(LIsNull* instr) {
|
||||
__ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
|
||||
__ testb(FieldOperand(scratch, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
__ j(not_zero, &true_value);
|
||||
__ j(not_zero, &true_value, Label::kNear);
|
||||
__ bind(&false_value);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
__ bind(&done);
|
||||
@ -1749,12 +1750,13 @@ void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
|
||||
|
||||
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
||||
__ testl(input, Immediate(kSmiTagMask));
|
||||
NearLabel done, is_false;
|
||||
Label done, is_false;
|
||||
__ j(zero, &is_false);
|
||||
__ CmpObjectType(input, TestType(instr->hydrogen()), result);
|
||||
__ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
|
||||
__ j(NegateCondition(BranchCondition(instr->hydrogen())),
|
||||
&is_false, Label::kNear);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&is_false);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ bind(&done);
|
||||
@ -1798,8 +1800,8 @@ void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
__ testl(FieldOperand(input, String::kHashFieldOffset),
|
||||
Immediate(String::kContainsCachedArrayIndexMask));
|
||||
NearLabel done;
|
||||
__ j(zero, &done);
|
||||
Label done;
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ bind(&done);
|
||||
}
|
||||
@ -1878,7 +1880,7 @@ void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
|
||||
ASSERT(input.is(result));
|
||||
Register temp = ToRegister(instr->TempAt(0));
|
||||
Handle<String> class_name = instr->hydrogen()->class_name();
|
||||
NearLabel done;
|
||||
Label done;
|
||||
Label is_true, is_false;
|
||||
|
||||
EmitClassOfTest(&is_true, &is_false, class_name, input, temp);
|
||||
@ -1887,7 +1889,7 @@ void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
|
||||
|
||||
__ bind(&is_true);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&is_false);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
@ -1927,11 +1929,11 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
||||
__ push(ToRegister(instr->InputAt(0)));
|
||||
__ push(ToRegister(instr->InputAt(1)));
|
||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||
NearLabel true_value, done;
|
||||
Label true_value, done;
|
||||
__ testq(rax, rax);
|
||||
__ j(zero, &true_value);
|
||||
__ j(zero, &true_value, Label::kNear);
|
||||
__ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
|
||||
__ bind(&done);
|
||||
@ -1981,7 +1983,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
||||
// This is the inlined call site instanceof cache. The two occurences of the
|
||||
// hole value will be patched to the last map/result pair generated by the
|
||||
// instanceof stub.
|
||||
NearLabel cache_miss;
|
||||
Label cache_miss;
|
||||
// Use a temp register to avoid memory operands with variable lengths.
|
||||
Register map = ToRegister(instr->TempAt(0));
|
||||
__ movq(map, FieldOperand(object, HeapObject::kMapOffset));
|
||||
@ -1989,7 +1991,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
||||
__ movq(kScratchRegister, factory()->the_hole_value(),
|
||||
RelocInfo::EMBEDDED_OBJECT);
|
||||
__ cmpq(map, kScratchRegister); // Patched to cached map.
|
||||
__ j(not_equal, &cache_miss);
|
||||
__ j(not_equal, &cache_miss, Label::kNear);
|
||||
// Patched to load either true or false.
|
||||
__ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
|
||||
#ifdef DEBUG
|
||||
@ -2004,7 +2006,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
||||
// before calling the deferred code.
|
||||
__ bind(&cache_miss); // Null is not an instance of anything.
|
||||
__ CompareRoot(object, Heap::kNullValueRootIndex);
|
||||
__ j(equal, &false_result);
|
||||
__ j(equal, &false_result, Label::kNear);
|
||||
|
||||
// String values are not instances of anything.
|
||||
__ JumpIfNotString(object, kScratchRegister, deferred->entry());
|
||||
@ -2071,11 +2073,11 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
|
||||
if (op == Token::GT || op == Token::LTE) {
|
||||
condition = ReverseCondition(condition);
|
||||
}
|
||||
NearLabel true_value, done;
|
||||
Label true_value, done;
|
||||
__ testq(rax, rax);
|
||||
__ j(condition, &true_value);
|
||||
__ j(condition, &true_value, Label::kNear);
|
||||
__ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&true_value);
|
||||
__ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
|
||||
__ bind(&done);
|
||||
@ -2248,23 +2250,23 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
} else {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
for (int i = 0; i < map_count - 1; ++i) {
|
||||
Handle<Map> map = instr->hydrogen()->types()->at(i);
|
||||
NearLabel next;
|
||||
Label next;
|
||||
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
|
||||
__ j(not_equal, &next);
|
||||
__ j(not_equal, &next, Label::kNear);
|
||||
EmitLoadFieldOrConstantFunction(result, object, map, name);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&next);
|
||||
}
|
||||
Handle<Map> map = instr->hydrogen()->types()->last();
|
||||
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
|
||||
if (instr->hydrogen()->need_generic()) {
|
||||
NearLabel generic;
|
||||
__ j(not_equal, &generic);
|
||||
Label generic;
|
||||
__ j(not_equal, &generic, Label::kNear);
|
||||
EmitLoadFieldOrConstantFunction(result, object, map, name);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&generic);
|
||||
__ Move(rcx, instr->hydrogen()->name());
|
||||
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
||||
@ -2297,10 +2299,10 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||
DeoptimizeIf(not_equal, instr->environment());
|
||||
|
||||
// Check whether the function has an instance prototype.
|
||||
NearLabel non_instance;
|
||||
Label non_instance;
|
||||
__ testb(FieldOperand(result, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kHasNonInstancePrototype));
|
||||
__ j(not_zero, &non_instance);
|
||||
__ j(not_zero, &non_instance, Label::kNear);
|
||||
|
||||
// Get the prototype or initial map from the function.
|
||||
__ movq(result,
|
||||
@ -2311,13 +2313,13 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||
DeoptimizeIf(equal, instr->environment());
|
||||
|
||||
// If the function does not have an initial map, we're done.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ CmpObjectType(result, MAP_TYPE, kScratchRegister);
|
||||
__ j(not_equal, &done);
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Get the prototype from the initial map.
|
||||
__ movq(result, FieldOperand(result, Map::kPrototypeOffset));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Non-instance prototype: Fetch prototype from constructor field
|
||||
// in the function's map.
|
||||
@ -2334,13 +2336,13 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
|
||||
Register input = ToRegister(instr->InputAt(0));
|
||||
__ movq(result, FieldOperand(input, JSObject::kElementsOffset));
|
||||
if (FLAG_debug_code) {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
|
||||
Heap::kFixedArrayMapRootIndex);
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
__ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
|
||||
Heap::kFixedCOWArrayMapRootIndex);
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
Register temp((result.is(rax)) ? rbx : rax);
|
||||
__ push(temp);
|
||||
__ movq(temp, FieldOperand(result, HeapObject::kMapOffset));
|
||||
@ -2462,15 +2464,15 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
// Check for arguments adapter frame.
|
||||
NearLabel done, adapted;
|
||||
Label done, adapted;
|
||||
__ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Cmp(Operand(result, StandardFrameConstants::kContextOffset),
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ j(equal, &adapted);
|
||||
__ j(equal, &adapted, Label::kNear);
|
||||
|
||||
// No arguments adaptor frame.
|
||||
__ movq(result, rbp);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Arguments adaptor frame present.
|
||||
__ bind(&adapted);
|
||||
@ -2485,7 +2487,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
|
||||
void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
NearLabel done;
|
||||
Label done;
|
||||
|
||||
// If no arguments adaptor frame the number of arguments is fixed.
|
||||
if (instr->InputAt(0)->IsRegister()) {
|
||||
@ -2494,7 +2496,7 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
||||
__ cmpq(rbp, ToOperand(instr->InputAt(0)));
|
||||
}
|
||||
__ movl(result, Immediate(scope()->num_parameters()));
|
||||
__ j(equal, &done);
|
||||
__ j(equal, &done, Label::kNear);
|
||||
|
||||
// Arguments adaptor frame present. Get argument length from there.
|
||||
__ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
||||
@ -2518,18 +2520,18 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
||||
|
||||
// If the receiver is null or undefined, we have to pass the global object
|
||||
// as a receiver.
|
||||
NearLabel global_object, receiver_ok;
|
||||
Label global_object, receiver_ok;
|
||||
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
|
||||
__ j(equal, &global_object);
|
||||
__ j(equal, &global_object, Label::kNear);
|
||||
__ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, &global_object);
|
||||
__ j(equal, &global_object, Label::kNear);
|
||||
|
||||
// The receiver should be a JS object.
|
||||
Condition is_smi = __ CheckSmi(receiver);
|
||||
DeoptimizeIf(is_smi, instr->environment());
|
||||
__ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
|
||||
DeoptimizeIf(below, instr->environment());
|
||||
__ jmp(&receiver_ok);
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
|
||||
__ bind(&global_object);
|
||||
// TODO(kmillikin): We have a hydrogen value for the global object. See
|
||||
@ -2550,10 +2552,10 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
||||
|
||||
// Loop through the arguments pushing them onto the execution
|
||||
// stack.
|
||||
NearLabel invoke, loop;
|
||||
Label invoke, loop;
|
||||
// length is a small non-negative integer, due to the test above.
|
||||
__ testl(length, length);
|
||||
__ j(zero, &invoke);
|
||||
__ j(zero, &invoke, Label::kNear);
|
||||
__ bind(&loop);
|
||||
__ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
|
||||
__ decl(length);
|
||||
@ -2800,9 +2802,10 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
||||
// xmm_scratch = 0.5
|
||||
__ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE);
|
||||
__ movq(xmm_scratch, kScratchRegister);
|
||||
NearLabel below_half;
|
||||
Label below_half;
|
||||
__ ucomisd(xmm_scratch, input_reg);
|
||||
__ j(above, &below_half); // If input_reg is NaN, this doesn't jump.
|
||||
// If input_reg is NaN, this doesn't jump.
|
||||
__ j(above, &below_half, Label::kNear);
|
||||
// input = input + 0.5
|
||||
// This addition might give a result that isn't the correct for
|
||||
// rounding, due to loss of precision, but only for a number that's
|
||||
@ -3109,9 +3112,9 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
{ // Clamp the value to [0..255].
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ testl(value, Immediate(0xFFFFFF00));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ setcc(negative, value); // 1 if negative, 0 if positive.
|
||||
__ decb(value); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
@ -3234,7 +3237,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
DeferredStringCharCodeAt* deferred =
|
||||
new DeferredStringCharCodeAt(this, instr);
|
||||
|
||||
NearLabel flat_string, ascii_string, done;
|
||||
Label flat_string, ascii_string, done;
|
||||
|
||||
// Fetch the instance type of the receiver into result register.
|
||||
__ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
@ -3243,7 +3246,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
// We need special handling for non-sequential strings.
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(result, Immediate(kStringRepresentationMask));
|
||||
__ j(zero, &flat_string);
|
||||
__ j(zero, &flat_string, Label::kNear);
|
||||
|
||||
// Handle cons strings and go to deferred code for the rest.
|
||||
__ testb(result, Immediate(kIsConsStringMask));
|
||||
@ -3270,7 +3273,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
__ bind(&flat_string);
|
||||
STATIC_ASSERT(kAsciiStringTag != 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string);
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
@ -3286,7 +3289,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
times_2,
|
||||
SeqTwoByteString::kHeaderSize));
|
||||
}
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
@ -3476,7 +3479,8 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
||||
void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||
XMMRegister result_reg,
|
||||
LEnvironment* env) {
|
||||
NearLabel load_smi, heap_number, done;
|
||||
NearLabel load_smi;
|
||||
Label heap_number, done;
|
||||
|
||||
// Smi check.
|
||||
__ JumpIfSmi(input_reg, &load_smi);
|
||||
@ -3484,7 +3488,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||
// Heap number map check.
|
||||
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
|
||||
Heap::kHeapNumberMapRootIndex);
|
||||
__ j(equal, &heap_number);
|
||||
__ j(equal, &heap_number, Label::kNear);
|
||||
|
||||
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
|
||||
DeoptimizeIf(not_equal, env);
|
||||
@ -3492,12 +3496,12 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
|
||||
// Convert undefined to NaN. Compute NaN as 0/0.
|
||||
__ xorps(result_reg, result_reg);
|
||||
__ divsd(result_reg, result_reg);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Heap number to XMM conversion.
|
||||
__ bind(&heap_number);
|
||||
__ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Smi to XMM conversion
|
||||
__ bind(&load_smi);
|
||||
@ -3518,7 +3522,7 @@ class DeferredTaggedToI: public LDeferredCode {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
NearLabel done, heap_number;
|
||||
Label done, heap_number;
|
||||
Register input_reg = ToRegister(instr->InputAt(0));
|
||||
|
||||
// Heap number map check.
|
||||
@ -3526,13 +3530,13 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
||||
Heap::kHeapNumberMapRootIndex);
|
||||
|
||||
if (instr->truncating()) {
|
||||
__ j(equal, &heap_number);
|
||||
__ j(equal, &heap_number, Label::kNear);
|
||||
// Check for undefined. Undefined is converted to zero for truncating
|
||||
// conversions.
|
||||
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
|
||||
DeoptimizeIf(not_equal, instr->environment());
|
||||
__ Set(input_reg, 0);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&heap_number);
|
||||
|
||||
@ -3613,11 +3617,11 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
||||
DeoptimizeIf(not_equal, instr->environment());
|
||||
DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel done;
|
||||
Label done;
|
||||
// The integer converted back is equal to the original. We
|
||||
// only have to test if we got -0 as an input.
|
||||
__ testl(result_reg, result_reg);
|
||||
__ j(not_zero, &done);
|
||||
__ j(not_zero, &done, Label::kNear);
|
||||
__ movmskpd(result_reg, input_reg);
|
||||
// Bit 0 contains the sign of the double in input_reg.
|
||||
// If input was positive, we are ok and return 0, otherwise
|
||||
@ -3785,7 +3789,7 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
||||
NearLabel materialized;
|
||||
Label materialized;
|
||||
// Registers will be used as follows:
|
||||
// rdi = JS function.
|
||||
// rcx = literals array.
|
||||
@ -3797,7 +3801,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
||||
instr->hydrogen()->literal_index() * kPointerSize;
|
||||
__ movq(rbx, FieldOperand(rcx, literal_offset));
|
||||
__ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &materialized);
|
||||
__ j(not_equal, &materialized, Label::kNear);
|
||||
|
||||
// Create regexp literal using runtime function
|
||||
// Result will be in rax.
|
||||
@ -3869,7 +3873,7 @@ void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
Label true_label;
|
||||
Label false_label;
|
||||
NearLabel done;
|
||||
Label done;
|
||||
|
||||
Condition final_branch_condition = EmitTypeofIs(&true_label,
|
||||
&false_label,
|
||||
@ -3878,7 +3882,7 @@ void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
|
||||
__ j(final_branch_condition, &true_label);
|
||||
__ bind(&false_label);
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&true_label);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
@ -3980,15 +3984,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
|
||||
void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
NearLabel true_label;
|
||||
NearLabel false_label;
|
||||
NearLabel done;
|
||||
Label true_label;
|
||||
Label done;
|
||||
|
||||
EmitIsConstructCall(result);
|
||||
__ j(equal, &true_label);
|
||||
__ j(equal, &true_label, Label::kNear);
|
||||
|
||||
__ LoadRoot(result, Heap::kFalseValueRootIndex);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
__ bind(&true_label);
|
||||
__ LoadRoot(result, Heap::kTrueValueRootIndex);
|
||||
@ -4013,10 +4016,10 @@ void LCodeGen::EmitIsConstructCall(Register temp) {
|
||||
__ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
||||
|
||||
// Skip the arguments adaptor frame if it exists.
|
||||
NearLabel check_frame_marker;
|
||||
Label check_frame_marker;
|
||||
__ Cmp(Operand(temp, StandardFrameConstants::kContextOffset),
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ j(not_equal, &check_frame_marker);
|
||||
__ j(not_equal, &check_frame_marker, Label::kNear);
|
||||
__ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
|
||||
|
||||
// Check the marker in the calling frame.
|
||||
@ -4080,9 +4083,9 @@ void LCodeGen::DoIn(LIn* instr) {
|
||||
|
||||
void LCodeGen::DoStackCheck(LStackCheck* instr) {
|
||||
// Perform stack overflow check.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
|
||||
__ j(above_equal, &done);
|
||||
__ j(above_equal, &done, Label::kNear);
|
||||
|
||||
StackCheckStub stub;
|
||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -344,13 +344,13 @@ void MacroAssembler::Assert(Condition cc, const char* msg) {
|
||||
|
||||
void MacroAssembler::AssertFastElements(Register elements) {
|
||||
if (emit_debug_code()) {
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
|
||||
Heap::kFixedArrayMapRootIndex);
|
||||
j(equal, &ok);
|
||||
j(equal, &ok, Label::kNear);
|
||||
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
|
||||
Heap::kFixedCOWArrayMapRootIndex);
|
||||
j(equal, &ok);
|
||||
j(equal, &ok, Label::kNear);
|
||||
Abort("JSObject with fast elements map has slow elements");
|
||||
bind(&ok);
|
||||
}
|
||||
@ -358,8 +358,8 @@ void MacroAssembler::AssertFastElements(Register elements) {
|
||||
|
||||
|
||||
void MacroAssembler::Check(Condition cc, const char* msg) {
|
||||
NearLabel L;
|
||||
j(cc, &L);
|
||||
Label L;
|
||||
j(cc, &L, Label::kNear);
|
||||
Abort(msg);
|
||||
// will not return here
|
||||
bind(&L);
|
||||
@ -371,9 +371,9 @@ void MacroAssembler::CheckStackAlignment() {
|
||||
int frame_alignment_mask = frame_alignment - 1;
|
||||
if (frame_alignment > kPointerSize) {
|
||||
ASSERT(IsPowerOf2(frame_alignment));
|
||||
NearLabel alignment_as_expected;
|
||||
Label alignment_as_expected;
|
||||
testq(rsp, Immediate(frame_alignment_mask));
|
||||
j(zero, &alignment_as_expected);
|
||||
j(zero, &alignment_as_expected, Label::kNear);
|
||||
// Abort if stack is not aligned.
|
||||
int3();
|
||||
bind(&alignment_as_expected);
|
||||
@ -384,9 +384,9 @@ void MacroAssembler::CheckStackAlignment() {
|
||||
void MacroAssembler::NegativeZeroTest(Register result,
|
||||
Register op,
|
||||
Label* then_label) {
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
testl(result, result);
|
||||
j(not_zero, &ok);
|
||||
j(not_zero, &ok, Label::kNear);
|
||||
testl(op, op);
|
||||
j(sign, then_label);
|
||||
bind(&ok);
|
||||
@ -832,8 +832,8 @@ void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
|
||||
if (allow_stub_calls()) {
|
||||
Assert(equal, "Uninitialized kSmiConstantRegister");
|
||||
} else {
|
||||
NearLabel ok;
|
||||
j(equal, &ok);
|
||||
Label ok;
|
||||
j(equal, &ok, Label::kNear);
|
||||
int3();
|
||||
bind(&ok);
|
||||
}
|
||||
@ -895,8 +895,8 @@ void MacroAssembler::Integer32ToSmi(Register dst, Register src) {
|
||||
void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
|
||||
if (emit_debug_code()) {
|
||||
testb(dst, Immediate(0x01));
|
||||
NearLabel ok;
|
||||
j(zero, &ok);
|
||||
Label ok;
|
||||
j(zero, &ok, Label::kNear);
|
||||
if (allow_stub_calls()) {
|
||||
Abort("Integer32ToSmiField writing to non-smi location");
|
||||
} else {
|
||||
@ -1397,7 +1397,6 @@ void MacroAssembler::SmiShiftLeft(Register dst,
|
||||
Register src1,
|
||||
Register src2) {
|
||||
ASSERT(!dst.is(rcx));
|
||||
NearLabel result_ok;
|
||||
// Untag shift amount.
|
||||
if (!dst.is(src1)) {
|
||||
movq(dst, src1);
|
||||
@ -1782,9 +1781,9 @@ void MacroAssembler::Throw(Register value) {
|
||||
// Before returning we restore the context from the frame pointer if not NULL.
|
||||
// The frame pointer is NULL in the exception handler of a JS entry frame.
|
||||
Set(rsi, 0); // Tentatively set context pointer to NULL
|
||||
NearLabel skip;
|
||||
Label skip;
|
||||
cmpq(rbp, Immediate(0));
|
||||
j(equal, &skip);
|
||||
j(equal, &skip, Label::kNear);
|
||||
movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
bind(&skip);
|
||||
ret(0);
|
||||
@ -1802,12 +1801,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
|
||||
Load(rsp, 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;
|
||||
cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
|
||||
j(equal, &done);
|
||||
j(equal, &done, Label::kNear);
|
||||
// Fetch the next handler in the list.
|
||||
const int kNextOffset = StackHandlerConstants::kNextOffset;
|
||||
movq(rsp, Operand(rsp, kNextOffset));
|
||||
@ -1899,9 +1898,9 @@ void MacroAssembler::CheckMap(Register obj,
|
||||
|
||||
|
||||
void MacroAssembler::AbortIfNotNumber(Register object) {
|
||||
NearLabel ok;
|
||||
Label ok;
|
||||
Condition is_smi = CheckSmi(object);
|
||||
j(is_smi, &ok);
|
||||
j(is_smi, &ok, Label::kNear);
|
||||
Cmp(FieldOperand(object, HeapObject::kMapOffset),
|
||||
isolate()->factory()->heap_number_map());
|
||||
Assert(equal, "Operand not a number");
|
||||
@ -1910,7 +1909,6 @@ void MacroAssembler::AbortIfNotNumber(Register object) {
|
||||
|
||||
|
||||
void MacroAssembler::AbortIfSmi(Register object) {
|
||||
NearLabel ok;
|
||||
Condition is_smi = CheckSmi(object);
|
||||
Assert(NegateCondition(is_smi), "Operand is a smi");
|
||||
}
|
||||
@ -1973,10 +1971,10 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
|
||||
j(not_equal, miss);
|
||||
|
||||
// Make sure that the function has an instance prototype.
|
||||
NearLabel non_instance;
|
||||
Label non_instance;
|
||||
testb(FieldOperand(result, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kHasNonInstancePrototype));
|
||||
j(not_zero, &non_instance);
|
||||
j(not_zero, &non_instance, Label::kNear);
|
||||
|
||||
// Get the prototype or initial map from the function.
|
||||
movq(result,
|
||||
@ -1989,13 +1987,13 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
|
||||
j(equal, miss);
|
||||
|
||||
// If the function does not have an initial map, we're done.
|
||||
NearLabel done;
|
||||
Label done;
|
||||
CmpObjectType(result, MAP_TYPE, kScratchRegister);
|
||||
j(not_equal, &done);
|
||||
j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Get the prototype from the initial map.
|
||||
movq(result, FieldOperand(result, Map::kPrototypeOffset));
|
||||
jmp(&done);
|
||||
jmp(&done, Label::kNear);
|
||||
|
||||
// Non-instance prototype: Fetch prototype from constructor field
|
||||
// in initial map.
|
||||
|
@ -1369,21 +1369,22 @@ void MacroAssembler::SmiMul(Register dst,
|
||||
ASSERT(!src2.is(kScratchRegister));
|
||||
|
||||
if (dst.is(src1)) {
|
||||
NearLabel failure, zero_correct_result;
|
||||
Label failure, zero_correct_result;
|
||||
movq(kScratchRegister, src1); // Create backup for later testing.
|
||||
SmiToInteger64(dst, src1);
|
||||
imul(dst, src2);
|
||||
j(overflow, &failure);
|
||||
j(overflow, &failure, Label::kNear);
|
||||
|
||||
// Check for negative zero result. If product is zero, and one
|
||||
// argument is negative, go to slow case.
|
||||
NearLabel correct_result;
|
||||
Label correct_result;
|
||||
testq(dst, dst);
|
||||
j(not_zero, &correct_result);
|
||||
j(not_zero, &correct_result, Label::kNear);
|
||||
|
||||
movq(dst, kScratchRegister);
|
||||
xor_(dst, src2);
|
||||
j(positive, &zero_correct_result); // Result was positive zero.
|
||||
// Result was positive zero.
|
||||
j(positive, &zero_correct_result, Label::kNear);
|
||||
|
||||
bind(&failure); // Reused failure exit, restores src1.
|
||||
movq(src1, kScratchRegister);
|
||||
@ -1399,9 +1400,9 @@ void MacroAssembler::SmiMul(Register dst,
|
||||
j(overflow, on_not_smi_result);
|
||||
// Check for negative zero result. If product is zero, and one
|
||||
// argument is negative, go to slow case.
|
||||
NearLabel correct_result;
|
||||
Label correct_result;
|
||||
testq(dst, dst);
|
||||
j(not_zero, &correct_result);
|
||||
j(not_zero, &correct_result, Label::kNear);
|
||||
// One of src1 and src2 is zero, the check whether the other is
|
||||
// negative.
|
||||
movq(kScratchRegister, src1);
|
||||
@ -1516,7 +1517,6 @@ void MacroAssembler::SmiDiv(Register dst,
|
||||
ASSERT(!src1.is(rdx));
|
||||
|
||||
// Check for 0 divisor (result is +/-Infinity).
|
||||
NearLabel positive_divisor;
|
||||
testq(src2, src2);
|
||||
j(zero, on_not_smi_result);
|
||||
|
||||
@ -1531,12 +1531,12 @@ void MacroAssembler::SmiDiv(Register dst,
|
||||
|
||||
// We overshoot a little and go to slow case if we divide min-value
|
||||
// by any negative value, not just -1.
|
||||
NearLabel safe_div;
|
||||
Label safe_div;
|
||||
testl(rax, Immediate(0x7fffffff));
|
||||
j(not_zero, &safe_div);
|
||||
j(not_zero, &safe_div, Label::kNear);
|
||||
testq(src2, src2);
|
||||
if (src1.is(rax)) {
|
||||
j(positive, &safe_div);
|
||||
j(positive, &safe_div, Label::kNear);
|
||||
movq(src1, kScratchRegister);
|
||||
jmp(on_not_smi_result);
|
||||
} else {
|
||||
@ -1552,8 +1552,8 @@ void MacroAssembler::SmiDiv(Register dst,
|
||||
// Check that the remainder is zero.
|
||||
testl(rdx, rdx);
|
||||
if (src1.is(rax)) {
|
||||
NearLabel smi_result;
|
||||
j(zero, &smi_result);
|
||||
Label smi_result;
|
||||
j(zero, &smi_result, Label::kNear);
|
||||
movq(src1, kScratchRegister);
|
||||
jmp(on_not_smi_result);
|
||||
bind(&smi_result);
|
||||
@ -1590,11 +1590,11 @@ void MacroAssembler::SmiMod(Register dst,
|
||||
SmiToInteger32(src2, src2);
|
||||
|
||||
// Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
|
||||
NearLabel safe_div;
|
||||
Label safe_div;
|
||||
cmpl(rax, Immediate(Smi::kMinValue));
|
||||
j(not_equal, &safe_div);
|
||||
j(not_equal, &safe_div, Label::kNear);
|
||||
cmpl(src2, Immediate(-1));
|
||||
j(not_equal, &safe_div);
|
||||
j(not_equal, &safe_div, Label::kNear);
|
||||
// Retag inputs and go slow case.
|
||||
Integer32ToSmi(src2, src2);
|
||||
if (src1.is(rax)) {
|
||||
@ -1613,9 +1613,9 @@ void MacroAssembler::SmiMod(Register dst,
|
||||
}
|
||||
// Check for a negative zero result. If the result is zero, and the
|
||||
// dividend is negative, go slow to return a floating point negative zero.
|
||||
NearLabel smi_result;
|
||||
Label smi_result;
|
||||
testl(rdx, rdx);
|
||||
j(not_zero, &smi_result);
|
||||
j(not_zero, &smi_result, Label::kNear);
|
||||
testq(src1, src1);
|
||||
j(negative, on_not_smi_result);
|
||||
bind(&smi_result);
|
||||
@ -1652,7 +1652,6 @@ void MacroAssembler::SmiShiftLogicalRight(Register dst,
|
||||
ASSERT(!dst.is(rcx));
|
||||
// dst and src1 can be the same, because the one case that bails out
|
||||
// is a shift by 0, which leaves dst, and therefore src1, unchanged.
|
||||
NearLabel result_ok;
|
||||
if (src1.is(rcx) || src2.is(rcx)) {
|
||||
movq(kScratchRegister, rcx);
|
||||
}
|
||||
@ -1665,8 +1664,8 @@ void MacroAssembler::SmiShiftLogicalRight(Register dst,
|
||||
shl(dst, Immediate(kSmiShift));
|
||||
testq(dst, dst);
|
||||
if (src1.is(rcx) || src2.is(rcx)) {
|
||||
NearLabel positive_result;
|
||||
j(positive, &positive_result);
|
||||
Label positive_result;
|
||||
j(positive, &positive_result, Label::kNear);
|
||||
if (src1.is(rcx)) {
|
||||
movq(src1, kScratchRegister);
|
||||
} else {
|
||||
@ -1938,7 +1937,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
|
||||
InvokeFlag flag,
|
||||
const CallWrapper& call_wrapper) {
|
||||
bool definitely_matches = false;
|
||||
NearLabel invoke;
|
||||
Label invoke;
|
||||
if (expected.is_immediate()) {
|
||||
ASSERT(actual.is_immediate());
|
||||
if (expected.immediate() == actual.immediate()) {
|
||||
@ -1962,14 +1961,14 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
|
||||
// case when we invoke function values without going through the
|
||||
// IC mechanism.
|
||||
cmpq(expected.reg(), Immediate(actual.immediate()));
|
||||
j(equal, &invoke);
|
||||
j(equal, &invoke, Label::kNear);
|
||||
ASSERT(expected.reg().is(rbx));
|
||||
Set(rax, actual.immediate());
|
||||
} else if (!expected.reg().is(actual.reg())) {
|
||||
// Both expected and actual are in (different) registers. This
|
||||
// is the case when we invoke functions using call and apply.
|
||||
cmpq(expected.reg(), actual.reg());
|
||||
j(equal, &invoke);
|
||||
j(equal, &invoke, Label::kNear);
|
||||
ASSERT(actual.reg().is(rax));
|
||||
ASSERT(expected.reg().is(rbx));
|
||||
}
|
||||
|
@ -1065,9 +1065,9 @@ void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) {
|
||||
|
||||
|
||||
void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) {
|
||||
NearLabel after_position;
|
||||
Label after_position;
|
||||
__ cmpq(rdi, Immediate(-by * char_size()));
|
||||
__ j(greater_equal, &after_position);
|
||||
__ j(greater_equal, &after_position, Label::kNear);
|
||||
__ movq(rdi, Immediate(-by * char_size()));
|
||||
// On RegExp code entry (where this operation is used), the character before
|
||||
// the current position is expected to be already loaded.
|
||||
|
@ -3300,9 +3300,9 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
{ // Clamp the value to [0..255].
|
||||
NearLabel done;
|
||||
Label done;
|
||||
__ testl(rdx, Immediate(0xFFFFFF00));
|
||||
__ j(zero, &done);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
__ setcc(negative, rdx); // 1 if negative, 0 if positive.
|
||||
__ decb(rdx); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
|
Loading…
Reference in New Issue
Block a user