Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Unified Diff: src/arm/lithium-codegen-arm.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/lithium-codegen-arm.cc
===================================================================
--- src/arm/lithium-codegen-arm.cc (revision 7180)
+++ src/arm/lithium-codegen-arm.cc (working copy)
@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "arm/lithium-codegen-arm.h"
+#include "arm/lithium-gap-resolver-arm.h"
#include "code-stubs.h"
#include "stub-cache.h"
@@ -33,7 +34,7 @@
namespace internal {
-class SafepointGenerator : public PostCallGenerator {
+class SafepointGenerator : public CallWrapper {
public:
SafepointGenerator(LCodeGen* codegen,
LPointerMap* pointers,
@@ -43,7 +44,24 @@
deoptimization_index_(deoptimization_index) { }
virtual ~SafepointGenerator() { }
- virtual void Generate() {
+ virtual void BeforeCall(int call_size) {
+ ASSERT(call_size >= 0);
+ // Ensure that we have enough space after the previous safepoint position
+ // for the generated code there.
+ int call_end = codegen_->masm()->pc_offset() + call_size;
+ int prev_jump_end =
+ codegen_->LastSafepointEnd() + Deoptimizer::patch_size();
+ if (call_end < prev_jump_end) {
+ int padding_size = prev_jump_end - call_end;
+ ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+ while (padding_size > 0) {
+ codegen_->masm()->nop();
+ padding_size -= Assembler::kInstrSize;
+ }
+ }
+ }
+
+ virtual void AfterCall() {
codegen_->RecordSafepoint(pointers_, deoptimization_index_);
}
@@ -54,157 +72,6 @@
};
-class LGapNode: public ZoneObject {
- public:
- explicit LGapNode(LOperand* operand)
- : operand_(operand), resolved_(false), visited_id_(-1) { }
-
- LOperand* operand() const { return operand_; }
- bool IsResolved() const { return !IsAssigned() || resolved_; }
- void MarkResolved() {
- ASSERT(!IsResolved());
- resolved_ = true;
- }
- int visited_id() const { return visited_id_; }
- void set_visited_id(int id) {
- ASSERT(id > visited_id_);
- visited_id_ = id;
- }
-
- bool IsAssigned() const { return assigned_from_.is_set(); }
- LGapNode* assigned_from() const { return assigned_from_.get(); }
- void set_assigned_from(LGapNode* n) { assigned_from_.set(n); }
-
- private:
- LOperand* operand_;
- SetOncePointer<LGapNode> assigned_from_;
- bool resolved_;
- int visited_id_;
-};
-
-
-LGapResolver::LGapResolver()
- : nodes_(32),
- identified_cycles_(4),
- result_(16),
- next_visited_id_(0) {
-}
-
-
-const ZoneList<LMoveOperands>* LGapResolver::Resolve(
- const ZoneList<LMoveOperands>* moves,
- LOperand* marker_operand) {
- nodes_.Rewind(0);
- identified_cycles_.Rewind(0);
- result_.Rewind(0);
- next_visited_id_ = 0;
-
- for (int i = 0; i < moves->length(); ++i) {
- LMoveOperands move = moves->at(i);
- if (!move.IsRedundant()) RegisterMove(move);
- }
-
- for (int i = 0; i < identified_cycles_.length(); ++i) {
- ResolveCycle(identified_cycles_[i], marker_operand);
- }
-
- int unresolved_nodes;
- do {
- unresolved_nodes = 0;
- for (int j = 0; j < nodes_.length(); j++) {
- LGapNode* node = nodes_[j];
- if (!node->IsResolved() && node->assigned_from()->IsResolved()) {
- AddResultMove(node->assigned_from(), node);
- node->MarkResolved();
- }
- if (!node->IsResolved()) ++unresolved_nodes;
- }
- } while (unresolved_nodes > 0);
- return &result_;
-}
-
-
-void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) {
- AddResultMove(from->operand(), to->operand());
-}
-
-
-void LGapResolver::AddResultMove(LOperand* from, LOperand* to) {
- result_.Add(LMoveOperands(from, to));
-}
-
-
-void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) {
- ZoneList<LOperand*> cycle_operands(8);
- cycle_operands.Add(marker_operand);
- LGapNode* cur = start;
- do {
- cur->MarkResolved();
- cycle_operands.Add(cur->operand());
- cur = cur->assigned_from();
- } while (cur != start);
- cycle_operands.Add(marker_operand);
-
- for (int i = cycle_operands.length() - 1; i > 0; --i) {
- LOperand* from = cycle_operands[i];
- LOperand* to = cycle_operands[i - 1];
- AddResultMove(from, to);
- }
-}
-
-
-bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) {
- ASSERT(a != b);
- LGapNode* cur = a;
- while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) {
- cur->set_visited_id(visited_id);
- cur = cur->assigned_from();
- }
-
- return cur == b;
-}
-
-
-bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) {
- ASSERT(a != b);
- return CanReach(a, b, next_visited_id_++);
-}
-
-
-void LGapResolver::RegisterMove(LMoveOperands move) {
- if (move.source()->IsConstantOperand()) {
- // Constant moves should be last in the machine code. Therefore add them
- // first to the result set.
- AddResultMove(move.source(), move.destination());
- } else {
- LGapNode* from = LookupNode(move.source());
- LGapNode* to = LookupNode(move.destination());
- if (to->IsAssigned() && to->assigned_from() == from) {
- move.Eliminate();
- return;
- }
- ASSERT(!to->IsAssigned());
- if (CanReach(from, to)) {
- // This introduces a cycle. Save.
- identified_cycles_.Add(from);
- }
- to->set_assigned_from(from);
- }
-}
-
-
-LGapNode* LGapResolver::LookupNode(LOperand* operand) {
- for (int i = 0; i < nodes_.length(); ++i) {
- if (nodes_[i]->operand()->Equals(operand)) return nodes_[i];
- }
-
- // No node found => create a new one.
- LGapNode* result = new LGapNode(operand);
- nodes_.Add(result);
- return result;
-}
-
-
#define __ masm()->
bool LCodeGen::GenerateCode() {
@@ -230,8 +97,8 @@
void LCodeGen::Abort(const char* format, ...) {
if (FLAG_trace_bailout) {
- SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
- PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name);
+ SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+ PrintF("Aborting LCodeGen in @\"%s\": ", *name);
va_list arguments;
va_start(arguments, format);
OS::VPrint(format, arguments);
@@ -294,6 +161,44 @@
}
}
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+ if (heap_slots > 0) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+ FastNewContextStub stub(heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+ }
+ RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+ // Context is returned in both r0 and cp. It replaces the context
+ // passed to us. It's saved in the stack and kept live in cp.
+ __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Copy any necessary parameters into the context.
+ int num_parameters = scope()->num_parameters();
+ for (int i = 0; i < num_parameters; i++) {
+ Slot* slot = scope()->parameter(i)->AsSlot();
+ if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+ (num_parameters - 1 - i) * kPointerSize;
+ // Load parameter from stack.
+ __ ldr(r0, MemOperand(fp, parameter_offset));
+ // Store it in the context.
+ __ mov(r1, Operand(Context::SlotOffset(slot->index())));
+ __ str(r0, MemOperand(cp, r1));
+ // Update the write barrier. This clobbers all involved
+ // registers, so we have to use two more registers to avoid
+ // clobbering cp.
+ __ mov(r2, Operand(cp));
+ __ RecordWrite(r2, Operand(r1), r3, r0);
+ }
+ }
+ Comment(";;; End allocate local context");
+ }
+
// Trace the call.
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
@@ -464,7 +369,6 @@
MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
- // TODO(regis): Revisit.
ASSERT(!op->IsRegister());
ASSERT(!op->IsDoubleRegister());
ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
@@ -480,6 +384,21 @@
}
+MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
+ ASSERT(op->IsDoubleStackSlot());
+ int index = op->index();
+ if (index >= 0) {
+ // Local or spill slot. Skip the frame pointer, function, context,
+ // and the first word of the double in the fixed part of the frame.
+ return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize);
+ } else {
+ // Incoming parameter. Skip the return address and the first word of
+ // the double.
+ return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize);
+ }
+}
+
+
void LCodeGen::WriteTranslation(LEnvironment* environment,
Translation* translation) {
if (environment == NULL) return;
@@ -671,7 +590,8 @@
Handle<DeoptimizationInputData> data =
Factory::NewDeoptimizationInputData(length, TENURED);
- data->SetTranslationByteArray(*translations_.CreateByteArray());
+ Handle<ByteArray> translations = translations_.CreateByteArray();
+ data->SetTranslationByteArray(*translations);
data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
Handle<FixedArray> literals =
@@ -751,6 +671,12 @@
}
+void LCodeGen::RecordSafepoint(int deoptimization_index) {
+ LPointerMap empty_pointers(RelocInfo::kNoPosition);
+ RecordSafepoint(&empty_pointers, deoptimization_index);
+}
+
+
void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
int arguments,
int deoptimization_index) {
@@ -787,116 +713,7 @@
void LCodeGen::DoParallelMove(LParallelMove* move) {
- // d0 must always be a scratch register.
- DoubleRegister dbl_scratch = d0;
- LUnallocated marker_operand(LUnallocated::NONE);
-
- Register core_scratch = scratch0();
- bool destroys_core_scratch = false;
-
- const ZoneList<LMoveOperands>* moves =
- resolver_.Resolve(move->move_operands(), &marker_operand);
- for (int i = moves->length() - 1; i >= 0; --i) {
- LMoveOperands move = moves->at(i);
- LOperand* from = move.source();
- LOperand* to = move.destination();
- ASSERT(!from->IsDoubleRegister() ||
- !ToDoubleRegister(from).is(dbl_scratch));
- ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(dbl_scratch));
- ASSERT(!from->IsRegister() || !ToRegister(from).is(core_scratch));
- ASSERT(!to->IsRegister() || !ToRegister(to).is(core_scratch));
- if (from == &marker_operand) {
- if (to->IsRegister()) {
- __ mov(ToRegister(to), core_scratch);
- ASSERT(destroys_core_scratch);
- } else if (to->IsStackSlot()) {
- __ str(core_scratch, ToMemOperand(to));
- ASSERT(destroys_core_scratch);
- } else if (to->IsDoubleRegister()) {
- __ vmov(ToDoubleRegister(to), dbl_scratch);
- } else {
- ASSERT(to->IsDoubleStackSlot());
- // TODO(regis): Why is vstr not taking a MemOperand?
- // __ vstr(dbl_scratch, ToMemOperand(to));
- MemOperand to_operand = ToMemOperand(to);
- __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
- }
- } else if (to == &marker_operand) {
- if (from->IsRegister() || from->IsConstantOperand()) {
- __ mov(core_scratch, ToOperand(from));
- destroys_core_scratch = true;
- } else if (from->IsStackSlot()) {
- __ ldr(core_scratch, ToMemOperand(from));
- destroys_core_scratch = true;
- } else if (from->IsDoubleRegister()) {
- __ vmov(dbl_scratch, ToDoubleRegister(from));
- } else {
- ASSERT(from->IsDoubleStackSlot());
- // TODO(regis): Why is vldr not taking a MemOperand?
- // __ vldr(dbl_scratch, ToMemOperand(from));
- MemOperand from_operand = ToMemOperand(from);
- __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
- }
- } else if (from->IsConstantOperand()) {
- if (to->IsRegister()) {
- __ mov(ToRegister(to), ToOperand(from));
- } else {
- ASSERT(to->IsStackSlot());
- __ mov(ip, ToOperand(from));
- __ str(ip, ToMemOperand(to));
- }
- } else if (from->IsRegister()) {
- if (to->IsRegister()) {
- __ mov(ToRegister(to), ToOperand(from));
- } else {
- ASSERT(to->IsStackSlot());
- __ str(ToRegister(from), ToMemOperand(to));
- }
- } else if (to->IsRegister()) {
- ASSERT(from->IsStackSlot());
- __ ldr(ToRegister(to), ToMemOperand(from));
- } else if (from->IsStackSlot()) {
- ASSERT(to->IsStackSlot());
- __ ldr(ip, ToMemOperand(from));
- __ str(ip, ToMemOperand(to));
- } else if (from->IsDoubleRegister()) {
- if (to->IsDoubleRegister()) {
- __ vmov(ToDoubleRegister(to), ToDoubleRegister(from));
- } else {
- ASSERT(to->IsDoubleStackSlot());
- // TODO(regis): Why is vstr not taking a MemOperand?
- // __ vstr(dbl_scratch, ToMemOperand(to));
- MemOperand to_operand = ToMemOperand(to);
- __ vstr(ToDoubleRegister(from), to_operand.rn(), to_operand.offset());
- }
- } else if (to->IsDoubleRegister()) {
- ASSERT(from->IsDoubleStackSlot());
- // TODO(regis): Why is vldr not taking a MemOperand?
- // __ vldr(ToDoubleRegister(to), ToMemOperand(from));
- MemOperand from_operand = ToMemOperand(from);
- __ vldr(ToDoubleRegister(to), from_operand.rn(), from_operand.offset());
- } else {
- ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot());
- // TODO(regis): Why is vldr not taking a MemOperand?
- // __ vldr(dbl_scratch, ToMemOperand(from));
- MemOperand from_operand = ToMemOperand(from);
- __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
- // TODO(regis): Why is vstr not taking a MemOperand?
- // __ vstr(dbl_scratch, ToMemOperand(to));
- MemOperand to_operand = ToMemOperand(to);
- __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
- }
- }
-
- if (destroys_core_scratch) {
- __ ldr(core_scratch, MemOperand(fp, -kPointerSize));
- }
-
- LInstruction* next = GetNextInstruction();
- if (next != NULL && next->IsLazyBailout()) {
- int pc = masm()->pc_offset();
- safepoints_.SetPcAfterGap(pc);
- }
+ resolver_.Resolve(move);
}
@@ -940,15 +757,6 @@
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
break;
}
- case CodeStub::StringCharAt: {
- StringCharAtStub stub;
- CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
- break;
- }
- case CodeStub::MathPow: {
- Abort("MathPowStub unimplemented.");
- break;
- }
case CodeStub::NumberToString: {
NumberToStringStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
@@ -966,7 +774,8 @@
}
case CodeStub::TranscendentalCache: {
__ ldr(r0, MemOperand(sp, 0));
- TranscendentalCacheStub stub(instr->transcendental_type());
+ TranscendentalCacheStub stub(instr->transcendental_type(),
+ TranscendentalCacheStub::TAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
break;
}
@@ -982,12 +791,36 @@
void LCodeGen::DoModI(LModI* instr) {
+ if (instr->hydrogen()->HasPowerOf2Divisor()) {
+ Register dividend = ToRegister(instr->InputAt(0));
+
+ int32_t divisor =
+ HConstant::cast(instr->hydrogen()->right())->Integer32Value();
+
+ if (divisor < 0) divisor = -divisor;
+
+ Label positive_dividend, done;
+ __ tst(dividend, Operand(dividend));
+ __ b(pl, &positive_dividend);
+ __ rsb(dividend, dividend, Operand(0));
+ __ and_(dividend, dividend, Operand(divisor - 1));
+ __ rsb(dividend, dividend, Operand(0), SetCC);
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ __ b(ne, &done);
+ DeoptimizeIf(al, instr->environment());
+ }
+ __ bind(&positive_dividend);
+ __ and_(dividend, dividend, Operand(divisor - 1));
+ __ bind(&done);
+ return;
+ }
+
class DeferredModI: public LDeferredCode {
public:
DeferredModI(LCodeGen* codegen, LModI* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() {
- codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD);
+ codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD);
}
private:
LModI* instr_;
@@ -1016,7 +849,7 @@
__ bind(&ok);
}
- // Try a few common cases before using the generic stub.
+ // Try a few common cases before using the stub.
Label call_stub;
const int kUnfolds = 3;
// Skip if either side is negative.
@@ -1042,9 +875,10 @@
__ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
// Perform modulo operation (scratch contains right - 1).
__ and_(result, scratch, Operand(left));
+ __ b(&done);
__ bind(&call_stub);
- // Call the generic stub. The numbers in r0 and r1 have
+ // Call the stub. The numbers in r0 and r1 have
// to be tagged to Smis. If that is not possible, deoptimize.
DeferredModI* deferred = new DeferredModI(this, instr);
__ TrySmiTag(left, &deoptimize, scratch);
@@ -1070,7 +904,7 @@
DeferredDivI(LCodeGen* codegen, LDivI* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() {
- codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV);
+ codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV);
}
private:
LDivI* instr_;
@@ -1123,7 +957,7 @@
__ mov(result, Operand(left, ASR, 2), LeaveCC, eq);
__ b(eq, &done);
- // Call the generic stub. The numbers in r0 and r1 have
+ // Call the stub. The numbers in r0 and r1 have
// to be tagged to Smis. If that is not possible, deoptimize.
DeferredDivI* deferred = new DeferredDivI(this, instr);
@@ -1145,19 +979,33 @@
template<int T>
-void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
- Token::Value op) {
+void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
+ Token::Value op) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
__ PushSafepointRegistersAndDoubles();
- GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
+ // Move left to r1 and right to r0 for the stub call.
+ if (left.is(r1)) {
+ __ Move(r0, right);
+ } else if (left.is(r0) && right.is(r1)) {
+ __ Swap(r0, r1, r2);
+ } else if (left.is(r0)) {
+ ASSERT(!right.is(r1));
+ __ mov(r1, r0);
+ __ mov(r0, right);
+ } else {
+ ASSERT(!left.is(r0) && !right.is(r0));
+ __ mov(r0, right);
+ __ mov(r1, left);
+ }
+ TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT);
__ CallStub(&stub);
RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
0,
Safepoint::kNoDeoptimizationIndex);
// Overwrite the stored value of r0 with the result of the stub.
- __ StoreToSafepointRegistersAndDoublesSlot(r0);
+ __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
__ PopSafepointRegistersAndDoubles();
}
@@ -1322,10 +1170,10 @@
}
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->InputAt(0));
- __ ldr(result, FieldMemOperand(array, PixelArray::kLengthOffset));
+ __ ldr(result, FieldMemOperand(array, ExternalArray::kLengthOffset));
}
@@ -1413,7 +1261,7 @@
__ vmov(r2, r3, right);
__ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
// Move the result in the double result register.
- __ vmov(ToDoubleRegister(instr->result()), r0, r1);
+ __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
// Restore r0-r3.
__ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
@@ -1431,10 +1279,7 @@
ASSERT(ToRegister(instr->InputAt(1)).is(r0));
ASSERT(ToRegister(instr->result()).is(r0));
- // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current
- // GenericBinaryOpStub:
- // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
- GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0);
+ TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
@@ -1896,6 +1741,19 @@
}
+void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
+ Register input = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
+
+ if (FLAG_debug_code) {
+ __ AbortIfNotString(input);
+ }
+
+ __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
+ __ IndexFromHash(result, result);
+}
+
+
void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
@@ -1903,10 +1761,10 @@
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
__ ldr(scratch,
- FieldMemOperand(input, String::kContainsCachedArrayIndexMask));
+ FieldMemOperand(input, String::kHashFieldOffset));
__ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
- __ LoadRoot(result, Heap::kTrueValueRootIndex, ne);
- __ LoadRoot(result, Heap::kFalseValueRootIndex, eq);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
}
@@ -1919,9 +1777,9 @@
int false_block = chunk_->LookupDestination(instr->false_block_id());
__ ldr(scratch,
- FieldMemOperand(input, String::kContainsCachedArrayIndexMask));
+ FieldMemOperand(input, String::kHashFieldOffset));
__ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
- EmitBranch(true_block, false_block, ne);
+ EmitBranch(true_block, false_block, eq);
}
@@ -2164,15 +2022,11 @@
__ bind(&before_push_delta);
__ BlockConstPoolFor(kAdditionalDelta);
__ mov(temp, Operand(delta * kPointerSize));
- __ StoreToSafepointRegisterSlot(temp);
- __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
- ASSERT_EQ(kAdditionalDelta,
- masm_->InstructionsGeneratedSince(&before_push_delta));
- RecordSafepointWithRegisters(
- instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+ __ StoreToSafepointRegisterSlot(temp, temp);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
// Put the result value into the result register slot and
// restore all registers.
- __ StoreToSafepointRegisterSlot(result);
+ __ StoreToSafepointRegisterSlot(result, result);
__ PopSafepointRegisters();
}
@@ -2292,17 +2146,13 @@
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
- __ ldr(result,
- MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
- __ ldr(result, ContextOperand(result, instr->slot_index()));
+ __ ldr(result, ContextOperand(context, instr->slot_index()));
}
void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
Register context = ToRegister(instr->context());
Register value = ToRegister(instr->value());
- __ ldr(context,
- MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
__ str(value, ContextOperand(context, instr->slot_index()));
if (instr->needs_write_barrier()) {
int offset = Context::SlotOffset(instr->slot_index());
@@ -2390,7 +2240,7 @@
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
__ cmp(scratch, ip);
__ b(eq, &done);
- __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+ __ LoadRoot(ip, Heap::kExternalPixelArrayMapRootIndex);
__ cmp(scratch, ip);
__ b(eq, &done);
__ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
@@ -2401,11 +2251,12 @@
}
-void LCodeGen::DoLoadPixelArrayExternalPointer(
- LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+ LLoadExternalArrayPointer* instr) {
Register to_reg = ToRegister(instr->result());
Register from_reg = ToRegister(instr->InputAt(0));
- __ ldr(to_reg, FieldMemOperand(from_reg, PixelArray::kExternalPointerOffset));
+ __ ldr(to_reg, FieldMemOperand(from_reg,
+ ExternalArray::kExternalPointerOffset));
}
@@ -2446,12 +2297,12 @@
void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
- Register external_elements = ToRegister(instr->external_pointer());
+ Register external_pointer = ToRegister(instr->external_pointer());
Register key = ToRegister(instr->key());
Register result = ToRegister(instr->result());
// Load the result.
- __ ldrb(result, MemOperand(external_elements, key));
+ __ ldrb(result, MemOperand(external_pointer, key));
}
@@ -2621,7 +2472,7 @@
LInstruction* instr) {
// Change context if needed.
bool change_context =
- (graph()->info()->closure()->context() != function->context()) ||
+ (info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
@@ -2705,7 +2556,7 @@
// Set the pointer to the new heap number in tmp.
if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
// Restore input_reg after call to runtime.
- __ LoadFromSafepointRegisterSlot(input);
+ __ LoadFromSafepointRegisterSlot(input, input);
__ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
__ bind(&allocated);
@@ -2716,7 +2567,7 @@
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
__ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
- __ str(tmp1, masm()->SafepointRegisterSlot(input));
+ __ StoreToSafepointRegisterSlot(tmp1, input);
__ PopSafepointRegisters();
__ bind(&done);
@@ -2770,41 +2621,6 @@
}
-// Truncates a double using a specific rounding mode.
-// Clears the z flag (ne condition) if an overflow occurs.
-void LCodeGen::EmitVFPTruncate(VFPRoundingMode rounding_mode,
- SwVfpRegister result,
- DwVfpRegister double_input,
- Register scratch1,
- Register scratch2) {
- Register prev_fpscr = scratch1;
- Register scratch = scratch2;
-
- // Set custom FPCSR:
- // - Set rounding mode.
- // - Clear vfp cumulative exception flags.
- // - Make sure Flush-to-zero mode control bit is unset.
- __ vmrs(prev_fpscr);
- __ bic(scratch, prev_fpscr, Operand(kVFPExceptionMask |
- kVFPRoundingModeMask |
- kVFPFlushToZeroMask));
- __ orr(scratch, scratch, Operand(rounding_mode));
- __ vmsr(scratch);
-
- // Convert the argument to an integer.
- __ vcvt_s32_f64(result,
- double_input,
- kFPSCRRounding);
-
- // Retrieve FPSCR.
- __ vmrs(scratch);
- // Restore FPSCR.
- __ vmsr(prev_fpscr);
- // Check for vfp exceptions.
- __ tst(scratch, Operand(kVFPExceptionMask));
-}
-
-
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
@@ -2812,11 +2628,11 @@
Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->TempAt(0));
- EmitVFPTruncate(kRoundToMinusInf,
- single_scratch,
- input,
- scratch1,
- scratch2);
+ __ EmitVFPTruncate(kRoundToMinusInf,
+ single_scratch,
+ input,
+ scratch1,
+ scratch2);
DeoptimizeIf(ne, instr->environment());
// Move the result back to general purpose register r0.
@@ -2833,6 +2649,30 @@
}
+void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
+ DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
+ Register scratch1 = scratch0();
+ Register scratch2 = result;
+ __ EmitVFPTruncate(kRoundToNearest,
+ double_scratch0().low(),
+ input,
+ scratch1,
+ scratch2);
+ DeoptimizeIf(ne, instr->environment());
+ __ vmov(result, double_scratch0().low());
+
+ // Test for -0.
+ Label done;
+ __ cmp(result, Operand(0));
+ __ b(ne, &done);
+ __ vmov(scratch1, input.high());
+ __ tst(scratch1, Operand(HeapNumber::kSignMask));
+ DeoptimizeIf(ne, instr->environment());
+ __ bind(&done);
+}
+
+
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
ASSERT(ToDoubleRegister(instr->result()).is(input));
@@ -2840,6 +2680,104 @@
}
+void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
+ DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
+ Register scratch = scratch0();
+ SwVfpRegister single_scratch = double_scratch0().low();
+ DoubleRegister double_scratch = double_scratch0();
+ ASSERT(ToDoubleRegister(instr->result()).is(input));
+
+ // Add +0 to convert -0 to +0.
+ __ mov(scratch, Operand(0));
+ __ vmov(single_scratch, scratch);
+ __ vcvt_f64_s32(double_scratch, single_scratch);
+ __ vadd(input, input, double_scratch);
+ __ vsqrt(input, input);
+}
+
+
+void LCodeGen::DoPower(LPower* instr) {
+ LOperand* left = instr->InputAt(0);
+ LOperand* right = instr->InputAt(1);
+ Register scratch = scratch0();
+ DoubleRegister result_reg = ToDoubleRegister(instr->result());
+ Representation exponent_type = instr->hydrogen()->right()->representation();
+ if (exponent_type.IsDouble()) {
+ // Prepare arguments and call C function.
+ __ PrepareCallCFunction(4, scratch);
+ __ vmov(r0, r1, ToDoubleRegister(left));
+ __ vmov(r2, r3, ToDoubleRegister(right));
+ __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+ } else if (exponent_type.IsInteger32()) {
+ ASSERT(ToRegister(right).is(r0));
+ // Prepare arguments and call C function.
+ __ PrepareCallCFunction(4, scratch);
+ __ mov(r2, ToRegister(right));
+ __ vmov(r0, r1, ToDoubleRegister(left));
+ __ CallCFunction(ExternalReference::power_double_int_function(), 4);
+ } else {
+ ASSERT(exponent_type.IsTagged());
+ ASSERT(instr->hydrogen()->left()->representation().IsDouble());
+
+ Register right_reg = ToRegister(right);
+
+ // Check for smi on the right hand side.
+ Label non_smi, call;
+ __ JumpIfNotSmi(right_reg, &non_smi);
+
+ // Untag smi and convert it to a double.
+ __ SmiUntag(right_reg);
+ SwVfpRegister single_scratch = double_scratch0().low();
+ __ vmov(single_scratch, right_reg);
+ __ vcvt_f64_s32(result_reg, single_scratch);
+ __ jmp(&call);
+
+ // Heap number map check.
+ __ bind(&non_smi);
+ __ ldr(scratch, FieldMemOperand(right_reg, HeapObject::kMapOffset));
+ __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+ __ cmp(scratch, Operand(ip));
+ DeoptimizeIf(ne, instr->environment());
+ int32_t value_offset = HeapNumber::kValueOffset - kHeapObjectTag;
+ __ add(scratch, right_reg, Operand(value_offset));
+ __ vldr(result_reg, scratch, 0);
+
+ // Prepare arguments and call C function.
+ __ bind(&call);
+ __ PrepareCallCFunction(4, scratch);
+ __ vmov(r0, r1, ToDoubleRegister(left));
+ __ vmov(r2, r3, result_reg);
+ __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+ }
+ // Store the result in the result register.
+ __ GetCFunctionDoubleResult(result_reg);
+}
+
+
+void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
+ ASSERT(ToDoubleRegister(instr->result()).is(d2));
+ TranscendentalCacheStub stub(TranscendentalCache::LOG,
+ TranscendentalCacheStub::UNTAGGED);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
+ ASSERT(ToDoubleRegister(instr->result()).is(d2));
+ TranscendentalCacheStub stub(TranscendentalCache::COS,
+ TranscendentalCacheStub::UNTAGGED);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
+ ASSERT(ToDoubleRegister(instr->result()).is(d2));
+ TranscendentalCacheStub stub(TranscendentalCache::SIN,
+ TranscendentalCacheStub::UNTAGGED);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
switch (instr->op()) {
case kMathAbs:
@@ -2848,9 +2786,24 @@
case kMathFloor:
DoMathFloor(instr);
break;
+ case kMathRound:
+ DoMathRound(instr);
+ break;
case kMathSqrt:
DoMathSqrt(instr);
break;
+ case kMathPowHalf:
+ DoMathPowHalf(instr);
+ break;
+ case kMathCos:
+ DoMathCos(instr);
+ break;
+ case kMathSin:
+ DoMathSin(instr);
+ break;
+ case kMathLog:
+ DoMathLog(instr);
+ break;
default:
Abort("Unimplemented type of LUnaryMathOperation.");
UNREACHABLE();
@@ -2962,9 +2915,9 @@
// Name is always in r2.
__ mov(r2, Operand(instr->name()));
- Handle<Code> ic(Builtins::builtin(info_->is_strict()
- ? Builtins::StoreIC_Initialize_Strict
- : Builtins::StoreIC_Initialize));
+ Handle<Code> ic(Builtins::builtin(
+ info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+ : Builtins::StoreIC_Initialize));
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -3001,12 +2954,25 @@
}
+void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+ Register external_pointer = ToRegister(instr->external_pointer());
+ Register key = ToRegister(instr->key());
+ Register value = ToRegister(instr->value());
+
+ // Clamp the value to [0..255].
+ __ Usat(value, 8, Operand(value));
+ __ strb(value, MemOperand(external_pointer, key, LSL, 0));
+}
+
+
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(r2));
ASSERT(ToRegister(instr->key()).is(r1));
ASSERT(ToRegister(instr->value()).is(r0));
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ Handle<Code> ic(Builtins::builtin(
+ info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+ : Builtins::KeyedStoreIC_Initialize));
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -3147,12 +3113,61 @@
__ AbortIfNotSmi(r0);
}
__ SmiUntag(r0);
- MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result);
- __ str(r0, result_stack_slot);
+ __ StoreToSafepointRegisterSlot(r0, result);
__ PopSafepointRegisters();
}
+void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
+ class DeferredStringCharFromCode: public LDeferredCode {
+ public:
+ DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
+ private:
+ LStringCharFromCode* instr_;
+ };
+
+ DeferredStringCharFromCode* deferred =
+ new DeferredStringCharFromCode(this, instr);
+
+ ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+ Register char_code = ToRegister(instr->char_code());
+ Register result = ToRegister(instr->result());
+ ASSERT(!char_code.is(result));
+
+ __ cmp(char_code, Operand(String::kMaxAsciiCharCode));
+ __ b(hi, deferred->entry());
+ __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
+ __ add(result, result, Operand(char_code, LSL, kPointerSizeLog2));
+ __ ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize));
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(result, ip);
+ __ b(eq, deferred->entry());
+ __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
+ Register char_code = ToRegister(instr->char_code());
+ Register result = ToRegister(instr->result());
+
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ __ mov(result, Operand(0));
+
+ __ PushSafepointRegisters();
+ __ SmiTag(char_code);
+ __ push(char_code);
+ __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
+ __ StoreToSafepointRegisterSlot(r0, result);
+ __ PopSafepointRegisters();
+}
+
+
void LCodeGen::DoStringLength(LStringLength* instr) {
Register string = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
@@ -3229,9 +3244,7 @@
// register is stored, as this register is in the pointer map, but contains an
// integer value.
__ mov(ip, Operand(0));
- int reg_stack_index = __ SafepointRegisterStackIndex(reg.code());
- __ str(ip, MemOperand(sp, reg_stack_index * kPointerSize));
-
+ __ StoreToSafepointRegisterSlot(ip, reg);
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
@@ -3242,7 +3255,7 @@
__ bind(&done);
__ sub(ip, reg, Operand(kHeapObjectTag));
__ vstr(dbl_scratch, ip, HeapNumber::kValueOffset);
- __ str(reg, MemOperand(sp, reg_stack_index * kPointerSize));
+ __ StoreToSafepointRegisterSlot(reg, reg);
__ PopSafepointRegisters();
}
@@ -3287,8 +3300,7 @@
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
- int reg_stack_index = __ SafepointRegisterStackIndex(reg.code());
- __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize));
+ __ StoreToSafepointRegisterSlot(r0, reg);
__ PopSafepointRegisters();
}
@@ -3368,19 +3380,30 @@
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
- Label done;
Register input_reg = ToRegister(instr->InputAt(0));
- Register scratch = scratch0();
- DoubleRegister dbl_scratch = d0;
- SwVfpRegister flt_scratch = s0;
- DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
+ Register scratch1 = scratch0();
+ Register scratch2 = ToRegister(instr->TempAt(0));
+ DwVfpRegister double_scratch = double_scratch0();
+ SwVfpRegister single_scratch = double_scratch.low();
+ ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
+ ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
+
+ Label done;
+
// Heap number map check.
- __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(scratch, Operand(ip));
+ __ cmp(scratch1, Operand(ip));
if (instr->truncating()) {
+ Register scratch3 = ToRegister(instr->TempAt(1));
+ DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
+ ASSERT(!scratch3.is(input_reg) &&
+ !scratch3.is(scratch1) &&
+ !scratch3.is(scratch2));
+ // Performs a truncating conversion of a floating point number as used by
+ // the JS bitwise operations.
Label heap_number;
__ b(eq, &heap_number);
// Check for undefined. Undefined is converted to zero for truncating
@@ -3392,36 +3415,38 @@
__ b(&done);
__ bind(&heap_number);
- __ sub(ip, input_reg, Operand(kHeapObjectTag));
- __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
- __ vcmp(dbl_tmp, 0.0); // Sets overflow bit in FPSCR flags if NaN.
- __ vcvt_s32_f64(flt_scratch, dbl_tmp);
- __ vmov(input_reg, flt_scratch); // 32-bit result of conversion.
- __ vmrs(pc); // Move vector status bits to normal status bits.
- // Overflow bit is set if dbl_tmp is Nan.
- __ cmn(input_reg, Operand(1), vc); // 0x7fffffff + 1 -> overflow.
- __ cmp(input_reg, Operand(1), vc); // 0x80000000 - 1 -> overflow.
- DeoptimizeIf(vs, instr->environment()); // Saturation may have occured.
+ __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
+ __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
+ __ EmitECMATruncate(input_reg,
+ double_scratch2,
+ single_scratch,
+ scratch1,
+ scratch2,
+ scratch3);
+
} else {
+ CpuFeatures::Scope scope(VFP3);
// Deoptimize if we don't have a heap number.
DeoptimizeIf(ne, instr->environment());
__ sub(ip, input_reg, Operand(kHeapObjectTag));
- __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
- __ vcvt_s32_f64(flt_scratch, dbl_tmp);
- __ vmov(input_reg, flt_scratch); // 32-bit result of conversion.
- // Non-truncating conversion means that we cannot lose bits, so we convert
- // back to check; note that using non-overlapping s and d regs would be
- // slightly faster.
- __ vcvt_f64_s32(dbl_scratch, flt_scratch);
- __ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp);
- DeoptimizeIf(ne, instr->environment()); // Not equal or unordered.
+ __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
+ __ EmitVFPTruncate(kRoundToZero,
+ single_scratch,
+ double_scratch,
+ scratch1,
+ scratch2,
+ kCheckForInexactConversion);
+ DeoptimizeIf(ne, instr->environment());
+ // Load the result.
+ __ vmov(input_reg, single_scratch);
+
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ tst(input_reg, Operand(input_reg));
+ __ cmp(input_reg, Operand(0));
__ b(ne, &done);
- __ vmov(lr, ip, dbl_tmp);
- __ tst(ip, Operand(1 << 31)); // Test sign bit.
+ __ vmov(scratch1, double_scratch.high());
+ __ tst(scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment());
}
}
@@ -3463,42 +3488,38 @@
void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
- LOperand* input = instr->InputAt(0);
- ASSERT(input->IsDoubleRegister());
- LOperand* result = instr->result();
- ASSERT(result->IsRegister());
-
- DoubleRegister double_input = ToDoubleRegister(input);
- Register result_reg = ToRegister(result);
- SwVfpRegister single_scratch = double_scratch0().low();
+ Register result_reg = ToRegister(instr->result());
Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->TempAt(0));
+ DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
+ DwVfpRegister double_scratch = double_scratch0();
+ SwVfpRegister single_scratch = double_scratch0().low();
- VFPRoundingMode rounding_mode = instr->truncating() ? kRoundToMinusInf
- : kRoundToNearest;
+ Label done;
- EmitVFPTruncate(rounding_mode,
- single_scratch,
- double_input,
- scratch1,
- scratch2);
- // Deoptimize if we had a vfp invalid exception.
- DeoptimizeIf(ne, instr->environment());
- // Retrieve the result.
- __ vmov(result_reg, single_scratch);
-
- if (instr->truncating() &&
- instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- Label done;
- __ cmp(result_reg, Operand(0));
- __ b(ne, &done);
- // Check for -0.
- __ vmov(scratch1, double_input.high());
- __ tst(scratch1, Operand(HeapNumber::kSignMask));
+ if (instr->truncating()) {
+ Register scratch3 = ToRegister(instr->TempAt(1));
+ __ EmitECMATruncate(result_reg,
+ double_input,
+ single_scratch,
+ scratch1,
+ scratch2,
+ scratch3);
+ } else {
+ VFPRoundingMode rounding_mode = kRoundToMinusInf;
+ __ EmitVFPTruncate(rounding_mode,
+ single_scratch,
+ double_input,
+ scratch1,
+ scratch2,
+ kCheckForInexactConversion);
+ // Deoptimize if we had a vfp invalid exception,
+ // including inexact operation.
DeoptimizeIf(ne, instr->environment());
-
+ // Retrieve the result.
+ __ vmov(result_reg, single_scratch);
+ }
__ bind(&done);
- }
}
@@ -3768,37 +3789,30 @@
Condition final_branch_condition = kNoCondition;
Register scratch = scratch0();
if (type_name->Equals(Heap::number_symbol())) {
- __ tst(input, Operand(kSmiTagMask));
- __ b(eq, true_label);
+ __ JumpIfSmi(input, true_label);
__ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(input, Operand(ip));
final_branch_condition = eq;
} else if (type_name->Equals(Heap::string_symbol())) {
- __ tst(input, Operand(kSmiTagMask));
- __ b(eq, false_label);
- __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ JumpIfSmi(input, false_label);
+ __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
+ __ b(ge, false_label);
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
- __ b(ne, false_label);
- __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
- final_branch_condition = lo;
+ final_branch_condition = eq;
} else if (type_name->Equals(Heap::boolean_symbol())) {
- __ LoadRoot(ip, Heap::kTrueValueRootIndex);
- __ cmp(input, ip);
+ __ CompareRoot(input, Heap::kTrueValueRootIndex);
__ b(eq, true_label);
- __ LoadRoot(ip, Heap::kFalseValueRootIndex);
- __ cmp(input, ip);
+ __ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = eq;
} else if (type_name->Equals(Heap::undefined_symbol())) {
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ cmp(input, ip);
+ __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ b(eq, true_label);
- __ tst(input, Operand(kSmiTagMask));
- __ b(eq, false_label);
+ __ JumpIfSmi(input, false_label);
// Check for undetectable objects => true.
__ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
@@ -3806,32 +3820,22 @@
final_branch_condition = ne;
} else if (type_name->Equals(Heap::function_symbol())) {
- __ tst(input, Operand(kSmiTagMask));
- __ b(eq, false_label);
- __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
- __ b(eq, true_label);
- // Regular expressions => 'function' (they are callable).
- __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
- final_branch_condition = eq;
+ __ JumpIfSmi(input, false_label);
+ __ CompareObjectType(input, input, scratch, FIRST_FUNCTION_CLASS_TYPE);
+ final_branch_condition = ge;
} else if (type_name->Equals(Heap::object_symbol())) {
- __ tst(input, Operand(kSmiTagMask));
- __ b(eq, false_label);
- __ LoadRoot(ip, Heap::kNullValueRootIndex);
- __ cmp(input, ip);
+ __ JumpIfSmi(input, false_label);
+ __ CompareRoot(input, Heap::kNullValueRootIndex);
__ b(eq, true_label);
- // Regular expressions => 'function', not 'object'.
- __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
- __ b(eq, false_label);
+ __ CompareObjectType(input, input, scratch, FIRST_JS_OBJECT_TYPE);
+ __ b(lo, false_label);
+ __ CompareInstanceType(input, scratch, FIRST_FUNCTION_CLASS_TYPE);
+ __ b(hs, false_label);
// Check for undetectable objects => false.
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
- __ b(ne, false_label);
- // Check for JS objects => true.
- __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
- __ b(lo, false_label);
- __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
- final_branch_condition = ls;
+ final_branch_condition = eq;
} else {
final_branch_condition = ne;
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698