Commit 751ec5d0 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

IA32: Avoid going into stubs or runtime code for bitops even if the

inputs are heap numbers or the result is a heap number (only with
SSE2).  Make it possible for a deferred code object to work without
spilling all registers.
Review URL: http://codereview.chromium.org/3054047

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5215 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent df8b3eb7
......@@ -77,14 +77,23 @@ void CodeGenerator::ProcessDeferred() {
// Generate the code.
Comment cmnt(masm_, code->comment());
masm_->bind(code->entry_label());
code->SaveRegisters();
if (code->AutoSaveAndRestore()) {
code->SaveRegisters();
}
code->Generate();
code->RestoreRegisters();
masm_->jmp(code->exit_label());
if (code->AutoSaveAndRestore()) {
code->RestoreRegisters();
code->Exit();
}
}
}
void DeferredCode::Exit() {
masm_->jmp(exit_label());
}
void CodeGenerator::SetFrame(VirtualFrame* new_frame,
RegisterFile* non_frame_registers) {
RegisterFile saved_counts;
......
......@@ -319,6 +319,15 @@ class DeferredCode: public ZoneObject {
void SaveRegisters();
void RestoreRegisters();
void Exit();
// If this returns true then all registers will be saved for the duration
// of the Generate() call. Otherwise the registers are not saved and the
// Generate() call must bracket runtime any runtime calls with calls to
// SaveRegisters() and RestoreRegisters(). In this case the Generate
// method must also call Exit() in order to return to the non-deferred
// code.
virtual bool AutoSaveAndRestore() { return true; }
protected:
MacroAssembler* masm_;
......
......@@ -1142,6 +1142,21 @@ void Assembler::rcl(Register dst, uint8_t imm8) {
}
void Assembler::rcr(Register dst, uint8_t imm8) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
ASSERT(is_uint5(imm8)); // illegal shift count
if (imm8 == 1) {
EMIT(0xD1);
EMIT(0xD8 | dst.code());
} else {
EMIT(0xC1);
EMIT(0xD8 | dst.code());
EMIT(imm8);
}
}
void Assembler::sar(Register dst, uint8_t imm8) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -625,6 +625,7 @@ class Assembler : public Malloced {
void or_(const Operand& dst, const Immediate& x);
void rcl(Register dst, uint8_t imm8);
void rcr(Register dst, uint8_t imm8);
void sar(Register dst, uint8_t imm8);
void sar_cl(Register dst);
......
This diff is collapsed.
......@@ -530,7 +530,7 @@ class CodeGenerator: public AstVisitor {
// Emits code sequence that jumps to deferred code if the inputs
// are not both smis. Cannot be in MacroAssembler because it takes
// advantage of TypeInfo to skip unneeded checks.
// a deferred code object.
void JumpIfNotBothSmiUsingTypeInfo(Register left,
Register right,
Register scratch,
......@@ -538,6 +538,15 @@ class CodeGenerator: public AstVisitor {
TypeInfo right_info,
DeferredCode* deferred);
// Emits code sequence that jumps to the label if the inputs
// are not both smis.
void JumpIfNotBothSmiUsingTypeInfo(Register left,
Register right,
Register scratch,
TypeInfo left_info,
TypeInfo right_info,
Label* on_non_smi);
// If possible, combine two constant smi values using op to produce
// a smi result, and push it on the virtual frame, all at compile time.
// Returns true if it succeeds. Otherwise it has no effect.
......
......@@ -377,6 +377,12 @@ void MacroAssembler::AbortIfNotSmi(Register object) {
}
void MacroAssembler::AbortIfSmi(Register object) {
test(object, Immediate(kSmiTagMask));
Assert(not_equal, "Operand a smi");
}
void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(ebp);
mov(ebp, Operand(esp));
......@@ -1510,6 +1516,61 @@ void MacroAssembler::Abort(const char* msg) {
}
void MacroAssembler::JumpIfNotNumber(Register reg,
TypeInfo info,
Label* on_not_number) {
if (FLAG_debug_code) AbortIfSmi(reg);
if (!info.IsNumber()) {
cmp(FieldOperand(reg, HeapObject::kMapOffset),
Factory::heap_number_map());
j(not_equal, on_not_number);
}
}
void MacroAssembler::ConvertToInt32(Register dst,
Register source,
Register scratch,
TypeInfo info,
Label* on_not_int32) {
if (FLAG_debug_code) {
AbortIfSmi(source);
AbortIfNotNumber(source);
}
if (info.IsInteger32()) {
cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset));
} else {
Label done;
bool push_pop = (scratch.is(no_reg) && dst.is(source));
ASSERT(!scratch.is(source));
if (push_pop) {
push(dst);
scratch = dst;
}
if (scratch.is(no_reg)) scratch = dst;
cvttsd2si(scratch, FieldOperand(source, HeapNumber::kValueOffset));
cmp(scratch, 0x80000000u);
if (push_pop || dst.is(source)) {
j(not_equal, &done);
if (push_pop) {
pop(dst);
jmp(on_not_int32);
}
} else {
j(equal, on_not_int32);
}
bind(&done);
if (push_pop) {
add(Operand(esp), Immediate(kPointerSize)); // Pop.
}
if (!scratch.is(dst)) {
mov(dst, scratch);
}
}
}
void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
Register instance_type,
Register scratch,
......
......@@ -29,6 +29,7 @@
#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
#include "assembler.h"
#include "type-info.h"
namespace v8 {
namespace internal {
......@@ -225,12 +226,44 @@ class MacroAssembler: public Assembler {
sar(reg, kSmiTagSize);
}
// Modifies the register even if it does not contain a Smi!
void SmiUntag(Register reg, TypeInfo info, Label* non_smi) {
ASSERT(kSmiTagSize == 1);
sar(reg, kSmiTagSize);
if (info.IsSmi()) {
ASSERT(kSmiTag == 0);
j(carry, non_smi);
}
}
// Modifies the register even if it does not contain a Smi!
void SmiUntag(Register reg, Label* is_smi) {
ASSERT(kSmiTagSize == 1);
sar(reg, kSmiTagSize);
ASSERT(kSmiTag == 0);
j(not_carry, is_smi);
}
// Assumes input is a heap object.
void JumpIfNotNumber(Register reg, TypeInfo info, Label* on_not_number);
// Assumes input is a heap number. Jumps on things out of range. Also jumps
// on the min negative int32. Ignores frational parts.
void ConvertToInt32(Register dst,
Register src, // Can be the same as dst.
Register scratch, // Can be no_reg or dst, but not src.
TypeInfo info,
Label* on_not_int32);
// Abort execution if argument is not a number. Used in debug code.
void AbortIfNotNumber(Register object);
// Abort execution if argument is not a smi. Used in debug code.
void AbortIfNotSmi(Register object);
// Abort execution if argument is a smi. Used in debug code.
void AbortIfSmi(Register object);
// ---------------------------------------------------------------------------
// Exception handling
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment