13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8.h"
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "mips/lithium-codegen-mips.h"
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "mips/lithium-gap-resolver-mips.h"
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "code-stubs.h"
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "stub-cache.h"
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass SafepointGenerator : public CallWrapper {
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator(LCodeGen* codegen,
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     LPointerMap* pointers,
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Safepoint::DeoptMode mode)
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : codegen_(codegen),
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        pointers_(pointers),
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        deopt_mode_(mode) { }
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual ~SafepointGenerator() { }
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void BeforeCall(int call_size) const { }
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void AfterCall() const {
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    codegen_->RecordSafepoint(pointers_, deopt_mode_);
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LCodeGen* codegen_;
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers_;
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Safepoint::DeoptMode deopt_mode_;
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define __ masm()->
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateCode() {
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("Z_Code generation", chunk());
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_unused());
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  status_ = GENERATING;
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CpuFeatures::Scope scope(FPU);
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CodeStub::GenerateFPStubs();
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // NONE indicates that the scope shouldn't actually generate code to set up
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done in GeneratePrologue).
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::NONE);
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GeneratePrologue() &&
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateBody() &&
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDeferredCode() &&
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateSafepointTable();
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::FinishCode(Handle<Code> code) {
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_done());
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_stack_slots(GetStackSlotCount());
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PopulateDeoptimizationData(code);
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::Abort(const char* format, ...) {
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_bailout) {
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmartArrayPointer<char> name(
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        info()->shared_info()->DebugName()->ToCString());
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("Aborting LCodeGen in @\"%s\": ", *name);
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    va_list arguments;
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    va_start(arguments, format);
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    OS::VPrint(format, arguments);
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    va_end(arguments);
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("\n");
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  status_ = ABORTED;
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::Comment(const char* format, ...) {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_code_comments) return;
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char buffer[4 * KB];
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringBuilder builder(buffer, ARRAY_SIZE(buffer));
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  va_list arguments;
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  va_start(arguments, format);
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  builder.AddFormattedList(format, arguments);
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  va_end(arguments);
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy the string before recording it in the assembler to avoid
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // issues when the stack allocated buffer goes out of scope.
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_t length = builder.position();
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Vector<char> copy = Vector<char>::New(length + 1);
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  memcpy(copy.start(), builder.Finalize(), copy.length());
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm()->RecordComment(copy.start());
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GeneratePrologue() {
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_generating());
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ stop("stop_at");
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a1: Callee's JS function.
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cp: Callee's context.
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // fp: Caller's frame pointer.
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // lr: Caller's pc.
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Strict mode functions and builtins need to replace the receiver
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // with undefined when called as functions (without an explicit
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // receiver object). r5 is zero for method calls and non-zero for
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // function calls.
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info_->is_classic_mode() || info_->is_native()) {
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&ok, eq, t1, Operand(zero_reg));
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int receiver_offset = scope()->num_parameters() * kPointerSize;
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a2, MemOperand(sp, receiver_offset));
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&ok);
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(ra, fp, cp, a1);
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(fp, sp, Operand(2 * kPointerSize));  // Adj. FP to point to saved FP.
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Reserve space for the stack slots needed by the code.
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int slots = GetStackSlotCount();
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (slots > 0) {
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_debug_code) {
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a0, Operand(slots));
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a2, Operand(kSlotsZapValue));
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label loop;
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&loop);
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(a2);
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(a0, a0, 1);
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&loop, ne, a0, Operand(zero_reg));
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(sp, sp, Operand(slots * kPointerSize));
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Possibly allocate a local context.
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap_slots > 0) {
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; Allocate local context");
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Argument to NewContext is the function, which is in a1.
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FastNewContextStub stub(heap_slots);
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepoint(Safepoint::kNoLazyDeopt);
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Context is returned in both v0 and cp.  It replaces the context
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // passed to us.  It's saved in the stack and kept live in cp.
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy any necessary parameters into the context.
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int num_parameters = scope()->num_parameters();
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < num_parameters; i++) {
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Variable* var = scope()->parameter(i);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->IsContextSlot()) {
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            (num_parameters - 1 - i) * kPointerSize;
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Load parameter from stack.
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(a0, MemOperand(fp, parameter_offset));
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Store it in the context.
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand target = ContextOperand(cp, var->index());
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(a0, target);
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier. This clobbers a3 and a0.
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            cp, target.offset(), a0, a3, kRAHasBeenSaved, kSaveFPRegs);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; End allocate local context");
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Trace the call.
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace) {
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EnsureSpaceForLazyDeopt();
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateBody() {
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_generating());
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool emit_instructions = true;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (current_instruction_ = 0;
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       !is_aborted() && current_instruction_ < instructions_->length();
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       current_instruction_++) {
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LInstruction* instr = instructions_->at(current_instruction_);
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->IsLabel()) {
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LLabel* label = LLabel::cast(instr);
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      emit_instructions = !label->HasReplacement();
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (emit_instructions) {
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->CompileToNative(this);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateDeferredCode() {
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_generating());
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (deferred_.length() > 0) {
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LDeferredCode* code = deferred_[i];
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(code->entry());
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Comment(";;; Deferred code @%d: %s.",
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              code->instruction_index(),
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              code->instr()->Mnemonic());
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      code->Generate();
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(code->exit());
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deferred code is the last part of the instruction sequence. Mark
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the generated code as done unless we bailed out.
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!is_aborted()) status_ = DONE;
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateDeoptJumpTable() {
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(plind): not clear that this will have advantage for MIPS.
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skipping it for now. Raised issue #100 for this.
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Abort("Unimplemented: %s", "GenerateDeoptJumpTable");
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateSafepointTable() {
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(is_done());
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.Emit(masm(), GetStackSlotCount());
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::ToRegister(int index) const {
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Register::FromAllocationIndex(index);
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::ToDoubleRegister(int index) const {
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return DoubleRegister::FromAllocationIndex(index);
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::ToRegister(LOperand* op) const {
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(op->IsRegister());
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ToRegister(op->index());
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsRegister()) {
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ToRegister(op->index());
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> literal = chunk_->LookupLiteral(const_op);
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (r.IsInteger32()) {
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(literal->IsNumber());
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(scratch, Operand(static_cast<int32_t>(literal->Number())));
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("EmitLoadRegister: Unsupported double immediate.");
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(r.IsTagged());
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (literal->IsSmi()) {
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ li(scratch, Operand(literal));
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       __ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal));
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return scratch;
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsStackSlot() || op->IsArgument()) {
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, ToMemOperand(op));
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return scratch;
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return scratch;
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(op->IsDoubleRegister());
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ToDoubleRegister(op->index());
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                FloatRegister flt_scratch,
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                DoubleRegister dbl_scratch) {
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsDoubleRegister()) {
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ToDoubleRegister(op->index());
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> literal = chunk_->LookupLiteral(const_op);
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (r.IsInteger32()) {
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(literal->IsNumber());
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(at, Operand(static_cast<int32_t>(literal->Number())));
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mtc1(at, flt_scratch);
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_d_w(dbl_scratch, flt_scratch);
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return dbl_scratch;
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("unsupported double immediate");
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsTagged()) {
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("unsupported tagged immediate");
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsStackSlot() || op->IsArgument()) {
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand mem_op = ToMemOperand(op);
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(dbl_scratch, mem_op);
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return dbl_scratch;
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return dbl_scratch;
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> literal = chunk_->LookupLiteral(op);
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return literal;
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::IsInteger32(LConstantOperand* op) const {
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return chunk_->LookupLiteralRepresentation(op).IsInteger32();
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint LCodeGen::ToInteger32(LConstantOperand* op) const {
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value = chunk_->LookupLiteral(op);
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      value->Number());
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return static_cast<int32_t>(value->Number());
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const {
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value = chunk_->LookupLiteral(op);
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return value->Number();
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochOperand LCodeGen::ToOperand(LOperand* op) {
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsConstantOperand()) {
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> literal = chunk_->LookupLiteral(const_op);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (r.IsInteger32()) {
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(literal->IsNumber());
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Operand(static_cast<int32_t>(literal->Number()));
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("ToOperand Unsupported double immediate.");
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(r.IsTagged());
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Operand(literal);
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsRegister()) {
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Operand(ToRegister(op));
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleRegister()) {
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Abort("ToOperand IsDoubleRegister unimplemented");
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Operand(0);
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Stack slots not implemented, use ToMemOperand instead.
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Operand(0);
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMemOperand LCodeGen::ToMemOperand(LOperand* op) const {
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!op->IsRegister());
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!op->IsDoubleRegister());
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int index = op->index();
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index >= 0) {
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Local or spill slot. Skip the frame pointer, function, and
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // context in the fixed part of the frame.
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return MemOperand(fp, -(index + 3) * kPointerSize);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Incoming parameter. Skip the return address.
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return MemOperand(fp, -(index - 1) * kPointerSize);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(op->IsDoubleStackSlot());
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int index = op->index();
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index >= 0) {
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Local or spill slot. Skip the frame pointer, function, context,
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // and the first word of the double in the fixed part of the frame.
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize);
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Incoming parameter. Skip the return address and the first word of
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the double.
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize);
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment,
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Translation* translation) {
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (environment == NULL) return;
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The translation includes one command per value in the environment.
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int translation_size = environment->values()->length();
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The output frame height does not include the parameters.
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int height = translation_size - environment->parameter_count();
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WriteTranslation(environment->outer(), translation);
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int closure_id = DefineDeoptimizationLiteral(environment->closure());
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (environment->frame_type()) {
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case JS_FUNCTION:
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->BeginJSFrame(environment->ast_id(), closure_id, height);
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case JS_CONSTRUCT:
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->BeginConstructStubFrame(closure_id, translation_size);
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case ARGUMENTS_ADAPTOR:
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < translation_size; ++i) {
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOperand* value = environment->values()->at(i);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // spilled_registers_ and spilled_double_registers_ are either
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // both NULL or both set.
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (environment->spilled_registers() != NULL && value != NULL) {
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (value->IsRegister() &&
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          environment->spilled_registers()[value->index()] != NULL) {
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        translation->MarkDuplicate();
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddToTranslation(translation,
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         environment->spilled_registers()[value->index()],
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         environment->HasTaggedValueAt(i));
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          value->IsDoubleRegister() &&
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          environment->spilled_double_registers()[value->index()] != NULL) {
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        translation->MarkDuplicate();
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddToTranslation(
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            translation,
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            environment->spilled_double_registers()[value->index()],
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            false);
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddToTranslation(translation, value, environment->HasTaggedValueAt(i));
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::AddToTranslation(Translation* translation,
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                LOperand* op,
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                bool is_tagged) {
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op == NULL) {
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(twuerthinger): Introduce marker operands to indicate that this value
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // is not present and must be reconstructed from the deoptimizer. Currently
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // this is only used for the arguments object.
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreArgumentsObject();
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsStackSlot()) {
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_tagged) {
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreStackSlot(op->index());
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreInt32StackSlot(op->index());
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleStackSlot()) {
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreDoubleStackSlot(op->index());
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsArgument()) {
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(is_tagged);
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int src_index = GetStackSlotCount() + op->index();
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreStackSlot(src_index);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsRegister()) {
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(op);
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_tagged) {
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreRegister(reg);
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreInt32Register(reg);
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleRegister()) {
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleRegister reg = ToDoubleRegister(op);
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreDoubleRegister(reg);
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int src_index = DefineDeoptimizationLiteral(literal);
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreLiteral(src_index);
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallCode(Handle<Code> code,
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        RelocInfo::Mode mode,
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LInstruction* instr) {
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code,
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               RelocInfo::Mode mode,
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               LInstruction* instr,
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               SafepointMode safepoint_mode) {
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr != NULL);
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(code, mode);
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallRuntime(const Runtime::Function* function,
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int num_arguments,
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           LInstruction* instr) {
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr != NULL);
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(pointers != NULL);
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(function, num_arguments);
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int argc,
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       LInstruction* instr) {
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntimeSaveDoubles(id);
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithRegisters(
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    Safepoint::DeoptMode mode) {
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!environment->HasBeenRegistered()) {
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Physical stack frame layout:
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // -x ............. -4  0 ..................................... y
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [incoming arguments] [spill slots] [pushed outgoing arguments]
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Layout of the environment:
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0 ..................................................... size-1
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [parameters] [locals] [expression stack including arguments]
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Layout of the translation:
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0 ........................................................ size - 1 + 4
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [expression stack including arguments] [locals] [4 words] [parameters]
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // |>------------  translation_size ------------<|
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int frame_count = 0;
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int jsframe_count = 0;
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++frame_count;
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (e->frame_type() == JS_FUNCTION) {
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ++jsframe_count;
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Translation translation(&translations_, frame_count, jsframe_count);
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    WriteTranslation(environment, &translation);
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int deoptimization_index = deoptimizations_.length();
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int pc_offset = masm()->pc_offset();
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment->Register(deoptimization_index,
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          translation.index(),
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    deoptimizations_.Add(environment);
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DeoptimizeIf(Condition cc,
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            LEnvironment* environment,
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register src1,
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            const Operand& src2) {
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(environment->HasBeenRegistered());
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int id = environment->deoptimization_index();
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (entry == NULL) {
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Abort("bailout was not prepared");
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(FLAG_deopt_every_n_times < 2);  // Other values not supported on MIPS.
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_deopt_every_n_times == 1 &&
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      info_->shared_info()->opt_count() == id) {
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trap_on_deopt) {
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip;
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (cc != al) {
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&skip, NegateCondition(cc), src1, src2);
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ stop("trap_on_deopt");
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&skip);
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(plind): The Arm port is a little different here, due to their
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // DeOpt jump table, which is not used for Mips yet.
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(entry, RelocInfo::RUNTIME_ENTRY, cc, src1, src2);
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = deoptimizations_.length();
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length == 0) return;
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<DeoptimizationInputData> data =
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewDeoptimizationInputData(length, TENURED);
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<ByteArray> translations = translations_.CreateByteArray();
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  data->SetTranslationByteArray(*translations);
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> literals =
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < deoptimization_literals_.length(); i++) {
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literals->set(i, *deoptimization_literals_[i]);
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  data->SetLiteralArray(*literals);
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Populate the deoptimization entries.
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < length; i++) {
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LEnvironment* env = deoptimizations_[i];
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    data->SetAstId(i, Smi::FromInt(env->ast_id()));
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    data->SetArgumentsStackHeight(i,
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Smi::FromInt(env->arguments_stack_height()));
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    data->SetPc(i, Smi::FromInt(env->pc_offset()));
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_deoptimization_data(*data);
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int result = deoptimization_literals_.length();
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < deoptimization_literals_.length(); ++i) {
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (deoptimization_literals_[i].is_identical_to(literal)) return i;
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  deoptimization_literals_.Add(literal);
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(deoptimization_literals_.length() == 0);
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const ZoneList<Handle<JSFunction> >* inlined_closures =
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      chunk()->inlined_closures();
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0, length = inlined_closures->length();
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i < length;
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i++) {
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DefineDeoptimizationLiteral(inlined_closures->at(i));
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inlined_function_count_ = deoptimization_literals_.length();
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt(
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LInstruction* instr, SafepointMode safepoint_mode) {
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepointWithRegisters(
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LPointerMap* pointers,
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Safepoint::Kind kind,
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int arguments,
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Safepoint::DeoptMode deopt_mode) {
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expected_safepoint_kind_ == kind);
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      kind, arguments, deopt_mode);
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < operands->length(); i++) {
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOperand* pointer = operands->at(i);
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (pointer->IsStackSlot()) {
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      safepoint.DefinePointerSlot(pointer->index());
7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      safepoint.DefinePointerRegister(ToRegister(pointer));
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kind & Safepoint::kWithRegisters) {
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Register cp always contains a pointer to the context.
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    safepoint.DefinePointerRegister(cp);
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(LPointerMap* pointers,
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Safepoint::DeoptMode deopt_mode) {
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap empty_pointers(RelocInfo::kNoPosition);
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(&empty_pointers, deopt_mode);
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int arguments,
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Safepoint::DeoptMode deopt_mode) {
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepointWithRegistersAndDoubles(
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LPointerMap* pointers,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int arguments,
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Safepoint::DeoptMode deopt_mode) {
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode);
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordPosition(int position) {
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (position == RelocInfo::kNoPosition) return;
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm()->positions_recorder()->RecordPosition(position);
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLabel(LLabel* label) {
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (label->is_loop_header()) {
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; B%d - LOOP entry", label->block_id());
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; B%d", label->block_id());
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(label->label());
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block_ = label->block_id();
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoGap(label);
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) {
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  resolver_.Resolve(move);
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGap(LGap* gap) {
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = LGap::FIRST_INNER_POSITION;
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i <= LGap::LAST_INNER_POSITION;
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i++) {
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LParallelMove* move = gap->GetParallelMove(inner_pos);
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (move != NULL) DoParallelMove(move);
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) {
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoGap(instr);
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoParameter(LParameter* instr) {
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Nothing to do.
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallStub(LCallStub* instr) {
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->hydrogen()->major_key()) {
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::RegExpConstructResult: {
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RegExpConstructResultStub stub;
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::RegExpExec: {
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RegExpExecStub stub;
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::SubString: {
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SubStringStub stub;
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::NumberToString: {
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      NumberToStringStub stub;
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::StringAdd: {
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StringAddStub stub(NO_STRING_ADD_FLAGS);
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::StringCompare: {
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StringCompareStub stub;
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CodeStub::TranscendentalCache: {
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a0, MemOperand(sp, 0));
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TranscendentalCacheStub stub(instr->transcendental_type(),
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   TranscendentalCacheStub::TAGGED);
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Nothing to do.
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoModI(LModI* instr) {
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register left = ToRegister(instr->InputAt(0));
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register result = ToRegister(instr->result());
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->HasPowerOf2Divisor()) {
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch0();
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!left.is(scratch));
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch, left);
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int32_t p2constant = HConstant::cast(
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instr->hydrogen()->right())->Integer32Value();
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(p2constant != 0);
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Result always takes the sign of the dividend (left).
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    p2constant = abs(p2constant);
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label positive_dividend;
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg));
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ subu(result, zero_reg, left);
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(result, result, p2constant - 1);
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &done);
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ subu(result, zero_reg, result);
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&positive_dividend);
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(result, scratch, p2constant - 1);
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // div runs in the background while we check for special cases.
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register right = EmitLoadRegister(instr->InputAt(1), scratch);
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ div(left, right);
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for x % 0.
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg));
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfhi(result);
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDivI(LDivI* instr) {
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register left = ToRegister(instr->InputAt(0));
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register right = ToRegister(instr->InputAt(1));
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register result = ToRegister(instr->result());
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS div is asynchronous - it will run in the background while we
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // check for special cases.
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ div(left, right);
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for x / 0.
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for (0 / -x) that will produce negative zero.
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label left_not_zero;
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&left_not_zero, ne, left, Operand(zero_reg));
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&left_not_zero);
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for (-kMinInt / -1).
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label left_not_min_int;
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&left_not_min_int);
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mfhi(result);
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mflo(result);
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMulI(LMulI* instr) {
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that result may alias left.
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(instr->InputAt(0));
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right_op = instr->InputAt(1);
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool bailout_on_minus_zero =
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_op->IsConstantOperand() && !can_overflow) {
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use optimized code for specific constants.
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (bailout_on_minus_zero && (constant < 0)) {
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The case of a null constant will be handled separately.
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If constant is negative and left is null, the result should be -0.
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg));
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (constant) {
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case -1:
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Subu(result, zero_reg, left);
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case 0:
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (bailout_on_minus_zero) {
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // If left is strictly negative and the constant is null, the
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // result is -0. Deoptimize if required, otherwise return 0.
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg));
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(result, zero_reg);
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case 1:
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Nothing to do.
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Move(result, left);
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Multiplying by powers of two and powers of two plus or minus
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // one can be done faster with shifted operands.
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // For other constants we emit standard code.
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int32_t mask = constant >> 31;
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        uint32_t constant_abs = (constant + mask) ^ mask;
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (IsPowerOf2(constant_abs) ||
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            IsPowerOf2(constant_abs - 1) ||
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            IsPowerOf2(constant_abs + 1)) {
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (IsPowerOf2(constant_abs)) {
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int32_t shift = WhichPowerOf2(constant_abs);
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sll(result, left, shift);
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (IsPowerOf2(constant_abs - 1)) {
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int32_t shift = WhichPowerOf2(constant_abs - 1);
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sll(result, left, shift);
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ Addu(result, result, left);
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (IsPowerOf2(constant_abs + 1)) {
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int32_t shift = WhichPowerOf2(constant_abs + 1);
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sll(result, left, shift);
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ Subu(result, result, left);
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Correct the sign of the result is the constant is negative.
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (constant < 0)  {
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ Subu(result, zero_reg, result);
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Generate standard code.
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ li(at, constant);
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Mul(result, left, at);
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register right = EmitLoadRegister(right_op, scratch);
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (bailout_on_minus_zero) {
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Or(ToRegister(instr->TempAt(0)), left, right);
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (can_overflow) {
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // hi:lo = left * right.
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mult(left, right);
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mfhi(scratch);
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mflo(result);
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sra(at, result, 31);
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(ne, instr->environment(), scratch, Operand(at));
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Mul(result, left, right);
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (bailout_on_minus_zero) {
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Bail out if the result is supposed to be negative zero.
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label done;
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&done, ne, result, Operand(zero_reg));
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(lt,
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   instr->environment(),
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   ToRegister(instr->TempAt(0)),
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Operand(zero_reg));
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&done);
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBitI(LBitI* instr) {
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* left_op = instr->InputAt(0);
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right_op = instr->InputAt(1);
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(left_op->IsRegister());
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(left_op);
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
10573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand right(no_reg);
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_op->IsStackSlot() || right_op->IsArgument()) {
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right = Operand(EmitLoadRegister(right_op, at));
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right = ToOperand(right_op);
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->op()) {
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_AND:
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(result, left, right);
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_OR:
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Or(result, left, right);
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_XOR:
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Xor(result, left, right);
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) {
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result may alias either of them.
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right_op = instr->InputAt(1);
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(instr->InputAt(0));
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_op->IsRegister()) {
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // No need to mask the right operand on MIPS, it is built into the variable
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // shift instructions.
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (instr->op()) {
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SAR:
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ srav(result, left, ToRegister(right_op));
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHR:
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ srlv(result, left, ToRegister(right_op));
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->can_deopt()) {
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHL:
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sllv(result, left, ToRegister(right_op));
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Mask the right_op operand.
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int value = ToInteger32(LConstantOperand::cast(right_op));
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (instr->op()) {
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SAR:
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sra(result, left, shift_count);
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHR:
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ srl(result, left, shift_count);
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (instr->can_deopt()) {
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ And(at, left, Operand(0x80000000));
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHL:
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sll(result, left, shift_count);
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSubI(LSubI* instr) {
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* left = instr->InputAt(0);
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right = instr->InputAt(1);
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!can_overflow) {
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (right->IsStackSlot() || right->IsArgument()) {
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, at);
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg));
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(right->IsRegister() || right->IsConstantOperand());
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // can_overflow.
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register overflow = scratch0();
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch1();
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (right->IsStackSlot() ||
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        right->IsArgument() ||
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        right->IsConstantOperand()) {
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, scratch);
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SubuAndCheckForOverflow(ToRegister(result),
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(left),
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 right_reg,
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 overflow);  // Reg at also used as scratch.
11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(right->IsRegister());
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Due to overflow check macros not supporting constant operands,
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // handling the IsConstantOperand case was moved to prev if clause.
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SubuAndCheckForOverflow(ToRegister(result),
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(left),
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(right),
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 overflow);  // Reg at also used as scratch.
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg));
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) {
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->result()->IsRegister());
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(ToRegister(instr->result()), Operand(instr->value()));
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) {
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->result()->IsDoubleRegister());
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  double v = instr->value();
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(result, v);
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) {
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value = instr->value();
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (value->IsSmi()) {
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(ToRegister(instr->result()), Operand(value));
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(ToRegister(instr->result()),
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<HeapObject>::cast(value));
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register array = ToRegister(instr->InputAt(0));
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(array, JSArray::kLengthOffset));
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register array = ToRegister(instr->InputAt(0));
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset));
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoElementsKind(LElementsKind* instr) {
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load map into |result|.
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(input, HeapObject::kMapOffset));
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the map's "bit field 2" into |result|. We only need the first byte,
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // but the following bit field extraction takes care of that anyway.
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(result, FieldMemOperand(result, Map::kBitField2Offset));
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Retrieve elements_kind from bit field 2.
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount);
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoValueOf(LValueOf* instr) {
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ToRegister(instr->TempAt(0));
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the object is a smi return the object.
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(result, input);
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, &done);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the object is not a value type, return the object.
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, map, map);
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE));
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(input, JSValue::kValueOffset));
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDateField(LDateField* instr) {
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->InputAt(0));
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = ToRegister(instr->TempAt(0));
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* index = instr->index();
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label runtime, done;
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(object.is(a0));
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result.is(v0));
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch.is(scratch0()));
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch.is(object));
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AbortIfSmi(object);
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(object, scratch, scratch);
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Assert(eq, "Trying to get date field from non-date.",
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scratch, Operand(JS_DATE_TYPE));
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(scratch, Operand(stamp));
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(scratch, MemOperand(scratch));
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&runtime, ne, scratch, Operand(scratch0()));
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(result, FieldMemOperand(object, JSDate::kValueOffset +
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            kPointerSize * index->value()));
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2, scratch);
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a1, Operand(index));
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBitNotI(LBitNotI* instr) {
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Nor(result, zero_reg, Operand(input));
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoThrow(LThrow* instr) {
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = EmitLoadRegister(instr->InputAt(0), at);
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(input_reg);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kThrow, 1, instr);
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ stop("Unreachable code.");
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAddI(LAddI* instr) {
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* left = instr->InputAt(0);
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right = instr->InputAt(1);
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!can_overflow) {
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (right->IsStackSlot() || right->IsArgument()) {
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, at);
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg));
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(right->IsRegister() || right->IsConstantOperand());
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // can_overflow.
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register overflow = scratch0();
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch1();
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (right->IsStackSlot() ||
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        right->IsArgument() ||
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        right->IsConstantOperand()) {
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, scratch);
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AdduAndCheckForOverflow(ToRegister(result),
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(left),
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 right_reg,
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 overflow);  // Reg at also used as scratch.
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(right->IsRegister());
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Due to overflow check macros not supporting constant operands,
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // handling the IsConstantOperand case was moved to prev if clause.
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AdduAndCheckForOverflow(ToRegister(result),
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(left),
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 ToRegister(right),
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 overflow);  // Reg at also used as scratch.
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg));
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) {
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->op()) {
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::ADD:
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add_d(result, left, right);
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::SUB:
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub_d(result, left, right);
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::MUL:
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mul_d(result, left, right);
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::DIV:
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ div_d(result, left, right);
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::MOD: {
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save a0-a3 on the stack.
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RegList saved_regs = a0.bit() | a1.bit() | a2.bit() | a3.bit();
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ MultiPush(saved_regs);
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ PrepareCallCFunction(0, 2, scratch0());
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SetCallCDoubleArguments(left, right);
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallCFunction(
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ExternalReference::double_fp_operation(Token::MOD, isolate()),
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          0, 2);
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Move the result in the double result register.
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ GetCFunctionDoubleResult(result);
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Restore saved register.
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ MultiPop(saved_regs);
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) {
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(0)).is(a1));
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(1)).is(a0));
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BinaryOpStub stub(instr->op(), NO_OVERWRITE);
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Other arch use a nop here, to signal that there is no inlined
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // patchable code. Mips does not need the nop, since our marker
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instruction (andi zero_reg) will never be used in normal code.
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint LCodeGen::GetNextEmittedBlock(int block) {
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LLabel* label = chunk_->GetLabel(i);
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!label->HasReplacement()) return i;
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return -1;
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitBranch(int left_block, int right_block,
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Condition cc, Register src1, const Operand& src2) {
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int next_block = GetNextEmittedBlock(current_block_);
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  right_block = chunk_->LookupDestination(right_block);
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  left_block = chunk_->LookupDestination(left_block);
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_block == left_block) {
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(left_block);
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (left_block == next_block) {
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block),
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              NegateCondition(cc), src1, src2);
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (right_block == next_block) {
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2);
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2);
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block));
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitBranchF(int left_block, int right_block,
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Condition cc, FPURegister src1, FPURegister src2) {
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int next_block = GetNextEmittedBlock(current_block_);
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  right_block = chunk_->LookupDestination(right_block);
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  left_block = chunk_->LookupDestination(left_block);
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_block == left_block) {
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(left_block);
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (left_block == next_block) {
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL,
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               NegateCondition(cc), src1, src2);
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (right_block == next_block) {
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2);
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2);
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block));
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBranch(LBranch* instr) {
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r.IsInteger32()) {
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(instr->InputAt(0));
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (r.IsDouble()) {
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleRegister reg = ToDoubleRegister(instr->InputAt(0));
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test the double value. Zero and NaN are false.
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitBranchF(true_block, false_block, ne, reg, kDoubleRegZero);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(r.IsTagged());
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(instr->InputAt(0));
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HType type = instr->hydrogen()->value()->type();
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (type.IsBoolean()) {
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(at, Heap::kTrueValueRootIndex);
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitBranch(true_block, false_block, eq, reg, Operand(at));
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (type.IsSmi()) {
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label* true_label = chunk_->GetAssemblyLabel(true_block);
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label* false_label = chunk_->GetAssemblyLabel(false_block);
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Avoid deopts in the case where we've never executed this path before.
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // undefined -> false.
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label, eq, reg, Operand(at));
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Boolean -> its value.
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kTrueValueRootIndex);
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(true_label, eq, reg, Operand(at));
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kFalseValueRootIndex);
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label, eq, reg, Operand(at));
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // 'null' -> false.
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kNullValueRootIndex);
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label, eq, reg, Operand(at));
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::SMI)) {
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Smis: 0 -> false, all other -> true.
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label, eq, reg, Operand(zero_reg));
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ JumpIfSmi(reg, true_label);
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (expected.NeedsMap()) {
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If we need a map later and have a Smi -> deopt.
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ And(at, reg, Operand(kSmiTagMask));
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      const Register map = scratch0();
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.NeedsMap()) {
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset));
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (expected.CanBeUndetectable()) {
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Undetectable -> false.
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ And(at, at, Operand(1 << Map::kIsUndetectable));
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Branch(false_label, ne, at, Operand(zero_reg));
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // spec object -> true.
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(true_label, ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::STRING)) {
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // String value -> false iff empty.
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label not_string;
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE));
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(true_label, ne, at, Operand(zero_reg));
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label);
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_string);
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // heap number -> false iff +0, -0, or NaN.
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        DoubleRegister dbl_scratch = double_scratch0();
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label not_heap_number;
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&not_heap_number, ne, map, Operand(at));
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ BranchF(true_label, false_label, ne, dbl_scratch, kDoubleRegZero);
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Falls through if dbl_scratch == 0.
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(false_label);
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_heap_number);
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We've seen something for the first time -> deopt.
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg));
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitGoto(int block) {
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  block = chunk_->LookupDestination(block);
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int next_block = GetNextEmittedBlock(current_block_);
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (block != next_block) {
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(chunk_->GetAssemblyLabel(block));
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGoto(LGoto* instr) {
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitGoto(instr->block_id());
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition cond = kNoCondition;
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (op) {
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ:
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ_STRICT:
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = eq;
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LT:
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? lo : lt;
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GT:
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? hi : gt;
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LTE:
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? ls : le;
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GTE:
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? hs : ge;
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::IN:
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::INSTANCEOF:
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cond;
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* left = instr->InputAt(0);
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* right = instr->InputAt(1);
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition cond = TokenToCondition(instr->op(), false);
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left->IsConstantOperand() && right->IsConstantOperand()) {
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We can statically evaluate the comparison.
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    double left_val = ToDouble(LConstantOperand::cast(left));
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    double right_val = ToDouble(LConstantOperand::cast(right));
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int next_block =
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EvalComparison(instr->op(), left_val, right_val) ? true_block
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       : false_block;
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(next_block);
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->is_double()) {
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Compare left and right as doubles and load the
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // resulting flags into the normal status register.
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FPURegister left_reg = ToDoubleRegister(left);
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FPURegister right_reg = ToDoubleRegister(right);
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If a NaN is involved, i.e. the result is unordered,
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // jump to false block label.
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ BranchF(NULL, chunk_->GetAssemblyLabel(false_block), eq,
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 left_reg, right_reg);
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitBranchF(true_block, false_block, cond, left_reg, right_reg);
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register cmp_left;
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Operand cmp_right = Operand(0);
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (right->IsConstantOperand()) {
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_left = ToRegister(left);
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_right = Operand(ToInteger32(LConstantOperand::cast(right)));
16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (left->IsConstantOperand()) {
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_left = ToRegister(right);
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_right = Operand(ToInteger32(LConstantOperand::cast(left)));
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We transposed the operands. Reverse the condition.
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cond = ReverseCondition(cond);
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_left = ToRegister(left);
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_right = Operand(ToRegister(right));
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitBranch(true_block, false_block, cond, cmp_left, cmp_right);
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(instr->InputAt(0));
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register right = ToRegister(instr->InputAt(1));
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, left, Operand(right));
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(instr->InputAt(0));
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, left,
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(instr->hydrogen()->right()));
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) {
16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
16793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->InputAt(0));
16803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the expression is known to be untagged or a smi, then it's definitely
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not null, and it can't be a an undetectable object.
16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->representation().IsSpecialization() ||
16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->hydrogen()->type().IsSmi()) {
16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(false_block);
16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap::RootListIndex nil_value = instr->nil() == kNullValue ?
16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kNullValueRootIndex :
16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Heap::kUndefinedValueRootIndex;
16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, nil_value);
16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->kind() == kStrictEquality) {
16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitBranch(true_block, false_block, eq, reg, Operand(at));
16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ?
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kUndefinedValueRootIndex :
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap::kNullValueRootIndex;
17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* true_label = chunk_->GetAssemblyLabel(true_block);
17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* false_label = chunk_->GetAssemblyLabel(false_block);
17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, reg, Operand(at));
17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, other_nil_value);  // In the delay slot.
17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, reg, Operand(at));
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(reg, false_label);  // In the delay slot.
17083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for undetectable objects by looking in the bit field in
17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the map. The object has already been smi checked.
17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch, scratch, 1 << Map::kIsUndetectable);
17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitBranch(true_block, false_block, ne, scratch, Operand(zero_reg));
17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitIsObject(Register input,
17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register temp1,
17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register temp2,
17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* is_not_object,
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* is_object) {
17233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, is_not_object);
17243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(temp2, Heap::kNullValueRootIndex);
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(is_object, eq, input, Operand(temp2));
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load map.
17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Undetectable objects behave like undefined.
17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(temp2, temp2, Operand(1 << Map::kIsUndetectable));
17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(is_not_object, ne, temp2, Operand(zero_reg));
17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load instance type and check that it is in object type range.
17363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
17373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(is_not_object,
17383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            lt, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return le;
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->InputAt(0));
17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp1 = ToRegister(instr->TempAt(0));
17473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp2 = scratch0();
17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* true_label = chunk_->GetAssemblyLabel(true_block);
17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* false_label = chunk_->GetAssemblyLabel(false_block);
17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition true_cond =
17553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitIsObject(reg, temp1, temp2, false_label, true_label);
17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, true_cond, temp2,
17583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
17593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitIsString(Register input,
17633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register temp1,
17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* is_not_string) {
17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, is_not_string);
17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, temp1, temp1);
17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return lt;
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->InputAt(0));
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp1 = ToRegister(instr->TempAt(0));
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* false_label = chunk_->GetAssemblyLabel(false_block);
17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition true_cond =
17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitIsString(reg, temp1, false_label);
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, true_cond, temp1,
17843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(FIRST_NONSTRING_TYPE));
17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
17903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = EmitLoadRegister(instr->InputAt(0), at);
17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, input_reg, kSmiTagMask);
17943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, at, Operand(zero_reg));
17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = ToRegister(instr->TempAt(0));
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset));
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
18083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, temp, Operand(1 << Map::kIsUndetectable));
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, ne, at, Operand(zero_reg));
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Condition ComputeCompareCondition(Token::Value op) {
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (op) {
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ_STRICT:
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ:
18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return eq;
18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LT:
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return lt;
18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GT:
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return gt;
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LTE:
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return le;
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GTE:
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ge;
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return kNoCondition;
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
18343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Token::Value op = instr->op();
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = CompareIC::GetUninitialized(op);
18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
18403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition condition = ComputeCompareCondition(op);
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, condition, v0, Operand(zero_reg));
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType from = instr->from();
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType to = instr->to();
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == FIRST_TYPE) return to;
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(from == to || to == LAST_TYPE);
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return from;
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType from = instr->from();
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType to = instr->to();
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == to) return eq;
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (to == LAST_TYPE) return hs;
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == FIRST_TYPE) return ls;
18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return eq;
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
18723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
18733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* false_label = chunk_->GetAssemblyLabel(false_block);
18753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, false_label);
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, scratch, scratch);
18793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block,
18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             false_block,
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             BranchCondition(instr->hydrogen()),
18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(TestType(instr->hydrogen())));
18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AbortIfNotString(input);
18933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(input, String::kHashFieldOffset));
18963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IndexFromHash(result, result);
18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoHasCachedArrayIndexAndBranch(
19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LHasCachedArrayIndexAndBranch* instr) {
19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch,
19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(input, String::kHashFieldOffset));
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask));
19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, at, Operand(zero_reg));
19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Branches to a label or falls through with the answer in flags.  Trashes
19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the temp registers, but not the input.
19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true,
19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* is_false,
19193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<String>class_name,
19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register input,
19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register temp,
19223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register temp2) {
19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!input.is(temp));
19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!input.is(temp2));
19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!temp.is(temp2));
19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, is_false);
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (class_name->IsEqualTo(CStrVector("Function"))) {
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assuming the following assertions, we can use the same compares to test
19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // for both being a function type and being in the object type range.
19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  FIRST_SPEC_OBJECT_TYPE + 1);
19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
19363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  LAST_SPEC_OBJECT_TYPE - 1);
19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, temp, temp2);
19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_false, lt, temp2, Operand(FIRST_SPEC_OBJECT_TYPE));
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_true, eq, temp2, Operand(FIRST_SPEC_OBJECT_TYPE));
19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_true, eq, temp2, Operand(LAST_SPEC_OBJECT_TYPE));
19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
19443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Faster code path to avoid two compares: subtract lower bound from the
19453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // actual type and do a signed compare with the width of the type range.
19463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, temp, temp2);
19473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Subu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a function.
19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(temp, Map::kConstructorOffset));
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Objects with a non-function constructor have class 'Object'.
19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(temp, temp2, temp2);
19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (class_name->IsEqualTo(CStrVector("Object"))) {
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_true, ne, temp2, Operand(JS_FUNCTION_TYPE));
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(is_false, ne, temp2, Operand(JS_FUNCTION_TYPE));
19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // temp now contains the constructor function. Grab the
19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instance class name from there.
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(temp,
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               SharedFunctionInfo::kInstanceClassNameOffset));
19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The class name we are testing against is a symbol because it's a literal.
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The name in the constructor is a symbol because of the way the context is
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // booted.  This routine isn't expected to work for random API-created
19723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // classes and it doesn't have to because you can't access it with natives
19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // syntax.  Since both sides are symbols it is sufficient to use an identity
19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // comparison.
19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // End with the address of this class_name instance in temp register.
19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS, the caller must do the comparison with Handle<String>class_name.
19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
19823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
19833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = scratch0();
19843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp2 = ToRegister(instr->TempAt(0));
19853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> class_name = instr->hydrogen()->class_name();
19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* true_label = chunk_->GetAssemblyLabel(true_block);
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* false_label = chunk_->GetAssemblyLabel(false_block);
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, temp, Operand(class_name));
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->InputAt(0));
20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = ToRegister(instr->TempAt(0));
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = instr->true_block_id();
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = instr->false_block_id();
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, temp, Operand(instr->map()));
20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) {
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label true_label, done;
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(0)).is(a0));  // Object is in a0.
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(1)).is(a1));  // Function is in a1.
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result.is(v0));
20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceofStub stub(InstanceofStub::kArgsInRegisters);
20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&true_label, eq, result, Operand(zero_reg));
20213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(result, Operand(factory()->false_value()));
20223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
20233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&true_label);
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(result, Operand(factory()->true_value()));
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredInstanceOfKnownGlobal: public LDeferredCode {
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  LInstanceOfKnownGlobal* instr)
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() {
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* map_check() { return &map_check_; }
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LInstanceOfKnownGlobal* instr_;
20433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label map_check_;
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredInstanceOfKnownGlobal* deferred;
20473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  deferred = new DeferredInstanceOfKnownGlobal(this, instr);
20483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done, false_result;
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->InputAt(0));
20513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = ToRegister(instr->TempAt(0));
20523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
20533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(object.is(a0));
20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result.is(v0));
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A Smi is not instance of anything.
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(object, &false_result);
20593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is the inlined call site instanceof cache. The two occurences of the
20613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // hole value will be patched to the last map/result pair generated by the
20623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instanceof stub.
20633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label cache_miss;
20643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = temp;
20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
20663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
20683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->map_check());  // Label for calculating code patching.
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We use Factory::the_hole_value() on purpose instead of loading from the
20703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // root array to force relocation to be able to later patch with
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the cached map.
20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
20733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
20743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(at, Operand(Handle<Object>(cell)));
20753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(at, FieldMemOperand(at, JSGlobalPropertyCell::kValueOffset));
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&cache_miss, ne, map, Operand(at));
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We use Factory::the_hole_value() on purpose instead of loading from the
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // root array to force relocation to be able to later patch
20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // with true or false.
20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE);
20813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The inlined call site cache did not match. Check null and string before
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // calling the deferred code.
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&cache_miss);
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Null is not instance of anything.
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(temp, Heap::kNullValueRootIndex);
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&false_result, eq, object, Operand(temp));
20893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // String values is not instance of anything.
20913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition cc = __ IsObjectStringType(object, temp, temp);
20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&false_result, cc, temp, Operand(zero_reg));
20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Go to the deferred code.
20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry());
20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&false_result);
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(result, Heap::kFalseValueRootIndex);
20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Here result has either true or false. Deferred code also produces true or
21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // false object.
21023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
21033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Label* map_check) {
21093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
21103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result.is(v0));
21113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  flags = static_cast<InstanceofStub::Flags>(
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      flags | InstanceofStub::kArgsInRegisters);
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  flags = static_cast<InstanceofStub::Flags>(
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      flags | InstanceofStub::kCallSiteInlineCheck);
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  flags = static_cast<InstanceofStub::Flags>(
21183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      flags | InstanceofStub::kReturnTrueFalseObject);
21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceofStub stub(flags);
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the temp register reserved by the instruction. This needs to be t0 as
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // its slot of the pushing of safepoint registers is used to communicate the
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // offset to the location of the map check.
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = ToRegister(instr->TempAt(0));
21273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(temp.is(t0));
21283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(InstanceofStub::right(), instr->function());
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kAdditionalDelta = 7;
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label before_push_delta;
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&before_push_delta);
21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE);
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ StoreToSafepointRegisterSlot(temp, temp);
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCodeGeneric(stub.GetCode(),
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  RelocInfo::CODE_TARGET,
21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  instr,
21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasDeoptimizationEnvironment());
21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->deoptimization_environment();
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Put the result value into the result register slot and
21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // restore all registers.
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(result, result);
21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) {
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Token::Value op = instr->op();
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = CompareIC::GetUninitialized(op);
21553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS there is no need for a "no inlined smi code" marker (nop).
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition condition = ComputeCompareCondition(op);
21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A minor optimization that relies on LoadRoot always emitting one
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instruction.
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg));
21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(3, masm()->InstructionsGeneratedSince(&done));
21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
21683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoReturn(LReturn* instr) {
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace) {
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the return value on the stack as the parameter.
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Runtime::TraceExit returns its parameter in v0.
21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);
21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kTraceExit, 1);
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(sp, fp);
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Pop(ra, fp);
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(sp, sp, Operand(sp_delta));
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ra);
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell())));
21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(at, JSGlobalPropertyCell::kValueOffset));
21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, instr->environment(), result, Operand(at));
21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->global_object()).is(a0));
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             : RelocInfo::CODE_TARGET_CONTEXT;
22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, mode, instr);
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value = ToRegister(instr->value());
22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register cell = scratch0();
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the cell.
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(cell, Operand(instr->hydrogen()->cell()));
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the cell we are storing to contains the hole it could have
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // been deleted from the property dictionary. In that case, we need
22183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to update the property details in the property dictionary to mark
22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it as no longer deleted.
22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We use a temp to check the payload.
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register payload = ToRegister(instr->TempAt(0));
22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
22253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, instr->environment(), payload, Operand(at));
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store the value.
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->global_object()).is(a1));
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->value()).is(a0));
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->StoreIC_Initialize_Strict()
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->StoreIC_Initialize();
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register context = ToRegister(instr->context());
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, ContextOperand(context, instr->slot_index()));
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), result, Operand(at));
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label is_not_hole;
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&is_not_hole, ne, result, Operand(at));
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&is_not_hole);
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register context = ToRegister(instr->context());
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value = ToRegister(instr->value());
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemOperand target = ContextOperand(context, instr->slot_index());
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip_assignment;
22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, target);
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(eq, instr->environment(), scratch, Operand(at));
22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&skip_assignment, ne, scratch, Operand(at));
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(value, target);
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HType type = instr->hydrogen()->value()->type();
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck check_needed =
22893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(context,
22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              target.offset(),
22923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              value,
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              scratch0(),
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kRAHasBeenSaved,
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kSaveFPRegs,
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              EMIT_REMEMBERED_SET,
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              check_needed);
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip_assignment);
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->InputAt(0));
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->is_in_object()) {
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(result, FieldMemOperand(object, instr->hydrogen()->offset()));
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(result, FieldMemOperand(result, instr->hydrogen()->offset()));
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Register object,
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Handle<Map> type,
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Handle<String> name) {
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
23213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  type->LookupInDescriptors(NULL, *name, &lookup);
23223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(lookup.IsFound() &&
23233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup.type() == FIELD) {
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index = lookup.GetLocalFieldIndexFromMap(*type);
23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset = index * kPointerSize;
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index < 0) {
23283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Negative property indices are in-object properties, indexed
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // from the end of the fixed part of the object.
23303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(result, FieldMemOperand(object, offset + type->instance_size()));
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
23323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Non-negative property indices are in the properties array.
23333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
23353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
23363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(result, function);
23393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
23453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
23463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int map_count = instr->hydrogen()->types()->length();
23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = instr->hydrogen()->name();
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (map_count == 0) {
23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(instr->hydrogen()->need_generic());
23513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a2, Operand(name));
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
23533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(ic, RelocInfo::CODE_TARGET, instr);
23543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < map_count - 1; ++i) {
23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> map = instr->hydrogen()->types()->at(i);
23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next;
23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&next, ne, scratch, Operand(map));
23613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitLoadFieldOrConstantFunction(result, object, map, name);
23623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&done);
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next);
23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> map = instr->hydrogen()->types()->last();
23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->need_generic()) {
23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label generic;
23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&generic, ne, scratch, Operand(map));
23693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitLoadFieldOrConstantFunction(result, object, map, name);
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&done);
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&generic);
23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a2, Operand(name));
23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallCode(ic, RelocInfo::CODE_TARGET, instr);
23753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
23763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(ne, instr->environment(), scratch, Operand(map));
23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitLoadFieldOrConstantFunction(result, object, map, name);
23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->object()).is(a0));
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Name is always in a2.
23893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
23903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
23963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
23973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function really is a function. Load map into the
24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register.
24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(function, result, scratch);
24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_FUNCTION_TYPE));
24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure that the function has an instance prototype.
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_instance;
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype));
24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&non_instance, ne, scratch, Operand(zero_reg));
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the prototype or initial map from the function.
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function has a prototype or an initial map.
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), result, Operand(at));
24183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the function does not have an initial map, we're done.
24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(result, scratch, scratch);
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, ne, scratch, Operand(MAP_TYPE));
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the prototype from the initial map.
24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Non-instance prototype: Fetch prototype from constructor field
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in initial map.
24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_instance);
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(result, Map::kConstructorOffset));
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All done.
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadElements(LLoadElements* instr) {
24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
24423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(input, JSObject::kElementsOffset));
24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done, fail;
24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
24483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &done, eq, scratch, Operand(at));
24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);  // In the delay slot.
24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, eq, scratch, Operand(at));
24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // |scratch| still contains |input|'s map.
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
24533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ext(scratch, scratch, Map::kElementsKindShift,
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Map::kElementsKindBitCount);
24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, eq, scratch,
24563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Operand(FAST_ELEMENTS));
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&fail, lt, scratch,
24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Operand(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
24593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, le, scratch,
24603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Operand(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fail);
24623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Abort("Check for fast or external elements failed.");
24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadExternalArrayPointer(
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LLoadExternalArrayPointer* instr) {
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register to_reg = ToRegister(instr->result());
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register from_reg  = ToRegister(instr->InputAt(0));
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(to_reg, FieldMemOperand(from_reg,
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                ExternalArray::kExternalPointerOffset));
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register arguments = ToRegister(instr->arguments());
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = ToRegister(instr->length());
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register index = ToRegister(instr->index());
24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Bailout index is not a valid argument index. Use unsigned check to get
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // negative check for free.
24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(plind): Shoud be optimized to do the sub before the DeoptimizeIf(),
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // as they do in Arm. It will save us an instruction.
24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ls, instr->environment(), length, Operand(index));
24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There are two words between the frame pointer and the last argument.
24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Subtracting from length accounts for one of them, add one more.
24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ subu(length, length, index);
24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(length, length, Operand(1));
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(length, length, kPointerSizeLog2);
24953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(at, arguments, Operand(length));
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, MemOperand(at, 0));
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->elements());
25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = EmitLoadRegister(instr->key(), scratch0());
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the result.
25073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, key, kPointerSizeLog2);  // Key indexes words.
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ addu(scratch, elements, scratch);
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(scratch, FixedArray::kHeaderSize));
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for the hole value.
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, instr->environment(), result, Operand(scratch));
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadKeyedFastDoubleElement(
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LLoadKeyedFastDoubleElement* instr) {
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->elements());
25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift_size =
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("array index constant value too big.");
25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
25373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(elements, elements, Operand(constant_key * (1 << shift_size) +
25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedDoubleArray::kHeaderSize - kHeapObjectTag));
25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(scratch, key, shift_size);
25443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(elements, elements, Operand(scratch));
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(elements, elements,
25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
25473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldc1(result, MemOperand(elements));
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadKeyedSpecializedArrayElement(
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LLoadKeyedSpecializedArrayElement* instr) {
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register external_pointer = ToRegister(instr->external_pointer());
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
25603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("array index constant value too big.");
25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift_size = ElementsKindToShiftSize(elements_kind);
25723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
25743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister result = ToDoubleRegister(instr->result());
25763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch0(), external_pointer, constant_key * (1 << shift_size));
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(scratch0(), key, shift_size);
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch0(), scratch0(), external_pointer);
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lwc1(result, MemOperand(scratch0()));
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_d_s(result, result);
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldc1(result, MemOperand(scratch0()));
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register result = ToRegister(instr->result());
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch0();
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand mem_operand(zero_reg);
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mem_operand = MemOperand(external_pointer,
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               constant_key * (1 << shift_size));
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(scratch, key, shift_size);
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch, scratch, external_pointer);
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mem_operand = MemOperand(scratch);
26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (elements_kind) {
26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_BYTE_ELEMENTS:
26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lb(result, mem_operand);
26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_PIXEL_ELEMENTS:
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
26073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(result, mem_operand);
26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_SHORT_ELEMENTS:
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lh(result, mem_operand);
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
26133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lhu(result, mem_operand);
26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_INT_ELEMENTS:
26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(result, mem_operand);
26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
26193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(result, mem_operand);
26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // TODO(danno): we could be more clever here, perhaps having a special
26213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // version of the stub that detects if the overflow case actually
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // happens, and generate code that returns a double rather than int.
26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        DeoptimizeIf(Ugreater_equal, instr->environment(),
26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            result, Operand(0x80000000));
26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_FLOAT_ELEMENTS:
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_DOUBLE_ELEMENTS:
26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case DICTIONARY_ELEMENTS:
26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case NON_STRICT_ARGUMENTS_ELEMENTS:
26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->object()).is(a1));
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->key()).is(a0));
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
26463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = scratch1();
26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the calling frame is an arguments adaptor frame.
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done, adapted;
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Xor(temp, result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Result is the frame pointer for the frame if not adapted and for the real
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // frame below the adaptor frame if adapted.
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Movn(result, fp, temp);  // Move only if temp is not equal to zero (ne).
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Movz(result, scratch, temp);  // Move only if temp is equal to zero (eq).
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elem = ToRegister(instr->InputAt(0));
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If no arguments adaptor frame the number of arguments is fixed.
26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(result, zero_reg, Operand(scope()->num_parameters()));
26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, eq, fp, Operand(elem));
26763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Arguments adaptor frame present. Get argument length from there.
26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(result);
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Argument length is in result register.
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register receiver = ToRegister(instr->receiver());
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the receiver is null or undefined, we have to pass the global
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // object as a receiver to normal functions. Values have to be
26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // passed unchanged to builtins and strict-mode functions.
26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label global_object, receiver_ok;
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do not transform the receiver to object for strict mode
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // functions.
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch,
27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch,
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do not transform the receiver to object for builtins.
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t strict_mode_function_mask =
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  1 <<  (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize);
27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize);
27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask));
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&receiver_ok, ne, scratch, Operand(zero_reg));
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal function. Replace undefined or null with global receiver.
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kNullValueRootIndex);
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&global_object, eq, receiver, Operand(scratch));
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&global_object, eq, receiver, Operand(scratch));
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deoptimize if the receiver is not a JS object.
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, receiver, Operand(kSmiTagMask));
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg));
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(receiver, scratch, scratch);
27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(lt, instr->environment(),
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               scratch, Operand(FIRST_SPEC_OBJECT_TYPE));
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&receiver_ok);
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&global_object);
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(receiver, GlobalObjectOperand());
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(receiver,
27303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&receiver_ok);
27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) {
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register receiver = ToRegister(instr->receiver());
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = ToRegister(instr->length());
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->elements());
27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(receiver.is(a0));  // Used for parameter count.
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(function.is(a1));  // Required by InvokeFunction.
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy the arguments to this function possibly from the
27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // adaptor frame below it.
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const uint32_t kArgumentsLimit = 1 * KB;
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(hi, instr->environment(), length, Operand(kArgumentsLimit));
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the receiver and use the register to keep the original
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // number of arguments.
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(receiver);
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(receiver, length);
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The arguments are at a one pointer size offset from elements.
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(elements, elements, Operand(1 * kPointerSize));
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Loop through the arguments pushing them onto the execution
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stack.
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label invoke, loop;
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // length is a small non-negative integer, due to the test above.
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg));
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, length, 2);
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, elements, scratch);
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, MemOperand(scratch));
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(scratch);
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(length, length, Operand(1));
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, length, 2);
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&invoke);
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator safepoint_generator(
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      this, pointers, Safepoint::kLazyDeopt);
27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The number of arguments is stored in receiver which is a0, as expected
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // by InvokeFunction.
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ParameterCount actual(receiver);
27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(function, actual, CALL_FUNCTION,
27803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    safepoint_generator, CALL_AS_METHOD);
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) {
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* argument = instr->InputAt(0);
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Abort("DoPushArgument not implemented for double type.");
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register argument_reg = EmitLoadRegister(argument, at);
27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(argument_reg);
27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) {
27973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(result, instr->hydrogen()->closure());
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoContext(LContext* instr) {
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, cp);
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoOuterContext(LOuterContext* instr) {
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register context = ToRegister(instr->context());
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs());
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The context is the first argument.
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(cp, scratch0(), scratch1());
28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kDeclareGlobals, 3, instr);
28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGlobalObject(LGlobalObject* instr) {
28263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, ContextOperand(cp, Context::GLOBAL_INDEX));
28283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
28323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register global = ToRegister(instr->global());
28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset));
28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function,
28393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 int arity,
28403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 LInstruction* instr,
28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 CallKind call_kind) {
28423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
28433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function->shared()->formal_parameter_count() == arity;
28443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
28463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (can_invoke_directly) {
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(a1, function);
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Change context if needed.
28513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool change_context =
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (info()->closure()->context() != function->context()) ||
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scope()->contains_with() ||
28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (scope()->num_heap_slots() > 0);
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (change_context) {
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set r0 to arguments count if adaption is not needed. Assumes that r0
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // is available to write to at this point.
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!function->NeedsArgumentsAdaption()) {
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a0, Operand(arity));
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke function.
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SetCallKind(t1, call_kind);
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Call(at);
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up deoptimization.
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ParameterCount count(arity);
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore context.
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(a0, v0);
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD);
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deoptimize if not a heap number.
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), scratch, Operand(at));
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
29013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register exponent = scratch0();
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch = no_reg;
29033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the sign of the argument. If the argument is positive, just
29053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // return it.
29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(result, input);
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, exponent, Operand(HeapNumber::kSignMask));
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, eq, at, Operand(zero_reg));
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Input is negative. Reverse its sign.
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve the value of all registers.
29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Registers were saved at the safepoint, so we can use
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // many scratch registers.
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp1 = input.is(a1) ? a0 : a1;
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp2 = input.is(a2) ? a0 : a2;
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp3 = input.is(a3) ? a0 : a3;
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp4 = input.is(t0) ? a0 : t0;
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // exponent: floating point exponent value.
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label allocated, slow;
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&allocated);
29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Slow case: Call the runtime system to do the number allocation.
29303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set the pointer to the new heap number in tmp.
29343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!tmp1.is(v0))
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(tmp1, v0);
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore input_reg after call to runtime.
29373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadFromSafepointRegisterSlot(input, input);
29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&allocated);
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // exponent: floating point exponent value.
29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // tmp1: allocated heap number.
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(exponent, exponent, Operand(~HeapNumber::kSignMask));
29443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ StoreToSafepointRegisterSlot(tmp1, result);
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, input);
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done));
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ subu(result, zero_reg, input);
29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Overflow if result is still negative, i.e. 0x80000000.
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Class for deferred case.
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    LUnaryMathOperation* instr)
29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() {
29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
29803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LUnaryMathOperation* instr_;
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r.IsDouble()) {
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister input = ToDoubleRegister(instr->InputAt(0));
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister result = ToDoubleRegister(instr->result());
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ abs_d(result, input);
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (r.IsInteger32()) {
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitIntegerMathAbs(instr);
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Representation is tagged.
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredMathAbsTaggedHeapNumber* deferred =
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new DeferredMathAbsTaggedHeapNumber(this, instr);
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register input = ToRegister(instr->InputAt(0));
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Smi check.
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(input, deferred->entry());
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If smi, handle it directly.
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitIntegerMathAbs(instr);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(deferred->exit());
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister single_scratch = double_scratch0().low();
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register except_flag = ToRegister(instr->TempAt(0));
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ EmitFPUTruncate(kRoundToMinusInf,
30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     single_scratch,
30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     input,
30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch1,
30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     except_flag);
30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deopt if the operation did not succeed.
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the result.
30233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mfc1(result, single_scratch);
30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test for -0.
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, ne, result, Operand(zero_reg));
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(scratch1, input.high());
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done, check_sign_on_zero;
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Extract exponent bits.
30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mfc1(result, input.high());
30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ext(scratch,
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         result,
30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         HeapNumber::kExponentShift,
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         HeapNumber::kExponentBits);
30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the number is in ]-0.5, +0.5[, the result is +/- 0.
30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip1;
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&skip1, gt, scratch, Operand(HeapNumber::kExponentBias - 2));
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&check_sign_on_zero);
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip1);
30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The following conversion will not work with numbers
30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // outside of ]-2^32, 2^32[.
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ge, instr->environment(), scratch,
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Operand(HeapNumber::kExponentBias + 32));
30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save the original sign for later comparison.
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, result, Operand(HeapNumber::kSignMask));
30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(double_scratch0(), 0.5);
30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add_d(double_scratch0(), input, double_scratch0());
30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check sign of the result: if the sign changed, the input
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // value was in ]0.5, 0[ and the result should be -0.
30743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mfc1(result, double_scratch0().high());
30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Xor(result, result, Operand(scratch));
30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ARM uses 'mi' here, which is 'lt'
30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(lt, instr->environment(), result,
30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Operand(zero_reg));
30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip2;
30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ARM uses 'mi' here, which is 'lt'
30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Negating it results in 'ge'
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&skip2, ge, result, Operand(zero_reg));
30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(result, zero_reg);
30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&skip2);
30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register except_flag = scratch;
30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ EmitFPUTruncate(kRoundToMinusInf,
30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     double_scratch0().low(),
30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     double_scratch0(),
30953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     result,
30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     except_flag);
30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
30993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mfc1(result, double_scratch0().low());
31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test for -0.
31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, ne, result, Operand(zero_reg));
31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_sign_on_zero);
31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(scratch, input.high());
31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch, scratch, Operand(HeapNumber::kSignMask));
31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sqrt_d(result, input);
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister temp = ToDoubleRegister(instr->TempAt(0));
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!input.is(result));
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that according to ECMA-262 15.8.2.13:
31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Math.pow(-Infinity, 0.5) == Infinity
31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Math.sqrt(-Infinity) == NaN
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(temp, -V8_INFINITY);
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input);
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up Infinity in the delay slot.
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result is overwritten if the branch is not taken.
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ neg_d(result, temp);
31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add +0 to convert -0 to +0.
31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add_d(result, input, kDoubleRegZero);
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sqrt_d(result, result);
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoPower(LPower* instr) {
31463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation exponent_type = instr->hydrogen()->right()->representation();
31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Having marked this as a call, we can use any registers.
31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Just make sure that the input/output registers are the expected ones.
31493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->InputAt(1)->IsDoubleRegister() ||
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         ToDoubleRegister(instr->InputAt(1)).is(f4));
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->InputAt(1)->IsRegister() ||
31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         ToRegister(instr->InputAt(1)).is(a2));
31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->InputAt(0)).is(f2));
31543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f0));
31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (exponent_type.IsTagged()) {
31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label no_deopt;
31583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(a2, &no_deopt);
31593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset));
31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), t3, Operand(at));
31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&no_deopt);
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MathPowStub stub(MathPowStub::TAGGED);
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (exponent_type.IsInteger32()) {
31653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MathPowStub stub(MathPowStub::INTEGER);
31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(exponent_type.IsDouble());
31693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MathPowStub stub(MathPowStub::DOUBLE);
31703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoRandom(LRandom* instr) {
31763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredDoRandom: public LDeferredCode {
31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
31783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
31793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
31803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredRandom(instr_); }
31813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
31833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LRandom* instr_;
31843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredDoRandom* deferred = new DeferredDoRandom(this, instr);
31873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Having marked this instruction as a call we can use any
31883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // registers.
31893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f0));
31903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(0)).is(a0));
31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSeedSize = sizeof(uint32_t);
31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kPointerSize == kSeedSize);
31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalContextOffset));
31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRandomSeedOffset =
31973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a2, FieldMemOperand(a0, kRandomSeedOffset));
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a2: FixedArray of the global context's random seeds
32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load state[0].
32023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a1, FieldMemOperand(a2, ByteArray::kHeaderSize));
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry(), eq, a1, Operand(zero_reg));
32043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load state[1].
32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a0, FieldMemOperand(a2, ByteArray::kHeaderSize + kSeedSize));
32063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a1: state[0].
32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a0: state[1].
32083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(a3, a1, Operand(0xFFFF));
32113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(18273));
32127a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch  __ Mul(a3, a3, t0);
32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ srl(a1, a1, 16);
32143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(a1, a3, a1);
32153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save state[0].
32163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(a1, FieldMemOperand(a2, ByteArray::kHeaderSize));
32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
32193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(a3, a0, Operand(0xFFFF));
32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(36969));
32217a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch  __ Mul(a3, a3, t0);
32223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ srl(a0, a0, 16),
32233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(a0, a3, a0);
32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save state[1].
32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(a0, FieldMemOperand(a2, ByteArray::kHeaderSize + kSeedSize));
32263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
32283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(a0, a0, Operand(0x3FFFF));
32293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(a1, a1, 14);
32303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(v0, a0, a1);
32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(0x41300000));
32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU.
32373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(f12, v0, a2);
32383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Move 0x4130000000000000 to FPU.
32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(f14, zero_reg, a2);
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Subtract to get the result.
32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub_d(f0, f12, f14);
32423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredRandom(LRandom* instr) {
32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PrepareCallCFunction(1, scratch0());
32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Return value is in v0.
32483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f4));
32533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::LOG,
32543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::UNTAGGED);
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
32563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathTan(LUnaryMathOperation* instr) {
32603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f4));
32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::TAN,
32623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::UNTAGGED);
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
32643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
32683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f4));
32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::COS,
32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::UNTAGGED);
32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToDoubleRegister(instr->result()).is(f4));
32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::SIN,
32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::UNTAGGED);
32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->op()) {
32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathAbs:
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathAbs(instr);
32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathFloor:
32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathFloor(instr);
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathRound:
32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathRound(instr);
32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
32943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathSqrt:
32953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathSqrt(instr);
32963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathPowHalf:
32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathPowHalf(instr);
32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathCos:
33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathCos(instr);
33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathSin:
33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathSin(instr);
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
33063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathTan:
33073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathTan(instr);
33083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
33093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathLog:
33103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DoMathLog(instr);
33113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("Unimplemented type of LUnaryMathOperation.");
33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->function()).is(a1));
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasPointerMap());
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasDeoptimizationEnvironment());
33233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
33263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ParameterCount count(instr->arity());
33273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallKeyed(LCallKeyed* instr) {
33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int arity = instr->arity();
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic =
33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallNamed(LCallNamed* instr) {
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int arity = instr->arity();
33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic =
33493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
33503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
33513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, mode, instr);
33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore context register.
33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallFunction(LCallFunction* instr) {
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->function()).is(a1));
33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int arity = instr->arity();
33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallGlobal(LCallGlobal* instr) {
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int arity = instr->arity();
33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic =
33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
33753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, mode, instr);
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
33843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallNew(LCallNew* instr) {
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(0)).is(a1));
33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a0, Operand(instr->arity()));
33933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) {
33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(instr->function(), instr->arity(), instr);
33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value = ToRegister(instr->value());
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int offset = instr->offset();
34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is(value));
34093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!instr->transition().is_null()) {
34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(scratch, Operand(instr->transition()));
34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the store.
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HType type = instr->hydrogen()->value()->type();
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiCheck check_needed =
34183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
34193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->is_in_object()) {
34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value, FieldMemOperand(object, offset));
34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrier()) {
34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the object for in-object properties.
34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(object,
34243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          offset,
34253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          value,
34263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          scratch,
34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kRAHasBeenSaved,
34283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kSaveFPRegs,
34293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
34303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          check_needed);
34313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
34323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
34333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
34343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value, FieldMemOperand(scratch, offset));
34353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrier()) {
34363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the properties array.
34373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object is used as a scratch register.
34383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(scratch,
34393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          offset,
34403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          value,
34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          object,
34423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kRAHasBeenSaved,
34433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kSaveFPRegs,
34443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
34453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          check_needed);
34463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
34473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
34523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->object()).is(a1));
34533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->value()).is(a0));
34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Name is always in a2.
34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(instr->name()));
34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->StoreIC_Initialize_Strict()
34593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->StoreIC_Initialize();
34603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
34613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
34653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(hs,
34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               instr->environment(),
34673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               ToRegister(instr->index()),
34683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Operand(ToRegister(instr->length())));
34693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
34733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value = ToRegister(instr->value());
34743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->object());
34753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
34763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
34773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the store.
34793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->key()->IsConstantOperand()) {
34803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
34813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
34823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset =
34833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
34843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value, FieldMemOperand(elements, offset));
34853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
34863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(scratch, key, kPointerSizeLog2);
34873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ addu(scratch, elements, scratch);
34883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value, FieldMemOperand(scratch, FixedArray::kHeaderSize));
34893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HType type = instr->hydrogen()->value()->type();
34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck check_needed =
34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute address of modified element and store it into key register.
34963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(elements,
34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   key,
34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   value,
35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kRAHasBeenSaved,
35013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kSaveFPRegs,
35023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   EMIT_REMEMBERED_SET,
35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   check_needed);
35043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreKeyedFastDoubleElement(
35093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStoreKeyedFastDoubleElement* instr) {
35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister value = ToDoubleRegister(instr->value());
35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->elements());
35123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
35133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
35143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
35163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_nan;
35173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calculate the effective address of the slot in the array to store the
35193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // double value.
35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
35213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
35223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
35233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("array index constant value too big.");
35243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
35273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift_size = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
35293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, elements, Operand(constant_key * (1 << shift_size) +
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedDoubleArray::kHeaderSize - kHeapObjectTag));
35323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(scratch, key, shift_size);
35343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, elements, Operand(scratch));
35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, scratch,
35363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
35373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_nan;
35403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for NaN. All NaNs must be canonicalized.
35413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ BranchF(NULL, &is_nan, eq, value, value);
35423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&not_nan);
35433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only load canonical NaN if the comparison above set the overflow.
35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&is_nan);
35463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double());
35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_nan);
35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sdc1(value, MemOperand(scratch));
35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreKeyedSpecializedArrayElement(
35543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStoreKeyedSpecializedArrayElement* instr) {
35553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register external_pointer = ToRegister(instr->external_pointer());
35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
35613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
35623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
35633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
35643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Abort("array index constant value too big.");
35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift_size = ElementsKindToShiftSize(elements_kind);
35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
35723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
35733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister value(ToDoubleRegister(instr->value()));
35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch0(), external_pointer, constant_key * (1 << shift_size));
35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
35773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(scratch0(), key, shift_size);
35783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch0(), scratch0(), external_pointer);
35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_s_d(double_scratch0(), value);
35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ swc1(double_scratch0(), MemOperand(scratch0()));
35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sdc1(value, MemOperand(scratch0()));
35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value(ToRegister(instr->value()));
35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand mem_operand(zero_reg);
35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch0();
35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mem_operand = MemOperand(external_pointer,
35933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               constant_key * (1 << shift_size));
35943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
35953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(scratch, key, shift_size);
35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch, scratch, external_pointer);
35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      mem_operand = MemOperand(scratch);
35983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (elements_kind) {
36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_PIXEL_ELEMENTS:
36013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_BYTE_ELEMENTS:
36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sb(value, mem_operand);
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_SHORT_ELEMENTS:
36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sh(value, mem_operand);
36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_INT_ELEMENTS:
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(value, mem_operand);
36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_FLOAT_ELEMENTS:
36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTERNAL_DOUBLE_ELEMENTS:
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case DICTIONARY_ELEMENTS:
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case NON_STRICT_ARGUMENTS_ELEMENTS:
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
36223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
36233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->object()).is(a2));
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->key()).is(a1));
36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->value()).is(a0));
36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->KeyedStoreIC_Initialize();
36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object_reg = ToRegister(instr->object());
36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register new_map_reg = ToRegister(instr->new_map_reg());
36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> from_map = instr->original_map();
36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> to_map = instr->transitioned_map();
36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind from_kind = from_map->elements_kind();
36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind to_kind = to_map->elements_kind();
36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ToRegister(instr->result()), object_reg);
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_applicable;
36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&not_applicable, ne, scratch, Operand(from_map));
36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(new_map_reg, Operand(to_map));
36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Write barrier.
36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch, kRAHasBeenSaved, kDontSaveFPRegs);
36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to_kind == FAST_DOUBLE_ELEMENTS) {
36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register fixed_object_reg = ToRegister(instr->temp_reg());
36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(fixed_object_reg.is(a2));
36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(new_map_reg.is(a3));
36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(fixed_object_reg, object_reg);
36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             RelocInfo::CODE_TARGET, instr);
36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register fixed_object_reg = ToRegister(instr->temp_reg());
36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(fixed_object_reg.is(a2));
36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(new_map_reg.is(a3));
36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(fixed_object_reg, object_reg);
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             RelocInfo::CODE_TARGET, instr);
36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_applicable);
36793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) {
36833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ToRegister(instr->left()));
36843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ToRegister(instr->right()));
36853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringAddStub stub(NO_STRING_CHECK_IN_STUB);
36863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
36873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredStringCharCodeAt: public LDeferredCode {
36923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
36933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStringCharCodeAt* instr_;
36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredStringCharCodeAt* deferred =
37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new DeferredStringCharCodeAt(this, instr);
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharLoadGenerator::Generate(masm(),
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->string()),
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->index()),
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->result()),
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    deferred->entry());
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register string = ToRegister(instr->string());
37143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(string);
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the index as a smi. This is safe because of the checks in
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // DoStringCharCodeAt above.
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->index()->IsConstantOperand()) {
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index)));
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(scratch);
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register index = ToRegister(instr->index());
37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiTag(index);
37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(index);
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AbortIfNotSmi(v0);
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(v0);
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredStringCharFromCode: public LDeferredCode {
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStringCharFromCode* instr_;
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredStringCharFromCode* deferred =
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new DeferredStringCharFromCode(this, instr);
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register char_code = ToRegister(instr->char_code());
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!char_code.is(result));
37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry(), hi,
37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            char_code, Operand(String::kMaxAsciiCharCode));
37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, char_code, kPointerSizeLog2);
37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(result, result, scratch);
37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(result, FixedArray::kHeaderSize));
37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry(), eq, result, Operand(scratch));
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register char_code = ToRegister(instr->char_code());
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiTag(char_code);
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(char_code);
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringLength(LStringLength* instr) {
37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register string = ToRegister(instr->InputAt(0));
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(string, String::kLengthOffset));
37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(input->IsRegister() || input->IsStackSlot());
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* output = instr->result();
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(output->IsDoubleRegister());
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister single_scratch = double_scratch0().low();
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (input->IsStackSlot()) {
38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch0();
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, ToMemOperand(input));
38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mtc1(scratch, single_scratch);
38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mtc1(ToRegister(input), single_scratch);
38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cvt_d_w(ToDoubleRegister(output), single_scratch);
38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) {
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredNumberTagI: public LDeferredCode {
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); }
38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LNumberTagI* instr_;
38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register src = ToRegister(instr->InputAt(0));
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = ToRegister(instr->result());
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register overflow = scratch0();
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr);
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiTagCheckOverflow(dst, src, overflow);
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ BranchOnOverflow(deferred->entry(), overflow);
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow;
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register src = ToRegister(instr->InputAt(0));
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = ToRegister(instr->result());
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister dbl_scratch = double_scratch0();
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve the value of all registers.
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There was overflow, so bits 30 and 31 of the original integer
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // disagree. Try to allocate a heap number in new space and store
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the value in there. If that fails, call the runtime system.
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (dst.is(src)) {
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiUntag(src, dst);
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Xor(src, src, Operand(0x80000000));
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mtc1(src, dbl_scratch);
38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cvt_d_w(dbl_scratch, dbl_scratch);
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_inline_new) {
38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex);
38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateHeapNumber(t1, a3, t0, t2, &slow);
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(dst, t1);
38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Slow case: Call the runtime system to do the number allocation.
38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&slow);
38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Put a valid pointer value in the stack slot where the result
38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // register is stored, as this register is in the pointer map, but contains an
38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // integer value.
38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(zero_reg, dst);
38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(dst, v0);
38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Done. Put the value in dbl_scratch into the value of the allocated heap
38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // number.
38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(dst, dst);
38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) {
38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredNumberTagD: public LDeferredCode {
38853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LNumberTagD* instr_;
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0));
38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->result());
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp1 = ToRegister(instr->TempAt(0));
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp2 = ToRegister(instr->TempAt(1));
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_inline_new) {
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(deferred->entry());
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
39133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
39143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->result());
39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(reg, zero_reg);
39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
39203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, reg);
39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) {
39263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
39273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0)));
39283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) {
39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
39333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
39353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->needs_check()) {
39363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kHeapObjectTag == 1);
39373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the input is a HeapObject, value of scratch won't be zero.
39383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch, input, Operand(kHeapObjectTag));
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiUntag(result, input);
39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
39413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
39423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiUntag(result, input);
39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitNumberUntagD(Register input_reg,
39483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                DoubleRegister result_reg,
39493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                bool deoptimize_on_undefined,
39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                bool deoptimize_on_minus_zero,
39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                LEnvironment* env) {
39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
39533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label load_smi, heap_number, done;
39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi check.
39573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
39583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number map check.
39603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (deoptimize_on_undefined) {
39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, env, scratch, Operand(at));
39643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
39653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label heap_number;
39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&heap_number, eq, scratch, Operand(at));
39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, env, input_reg, Operand(at));
39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Convert undefined to NaN.
39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kNanValueRootIndex);
39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset));
39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&heap_number);
39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number to double register conversion.
39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
39803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (deoptimize_on_minus_zero) {
39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(at, result_reg.low());
39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, ne, at, Operand(zero_reg));
39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(scratch, result_reg.high());
39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi to double register conversion
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&load_smi);
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch: untagged value of input_reg
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mtc1(scratch, result_reg);
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cvt_d_w(result_reg, result_reg);
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(instr->InputAt(0));
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = ToRegister(instr->TempAt(0));
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister double_scratch = double_scratch0();
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister single_scratch = double_scratch.low();
40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The input is a tagged HeapObject.
40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number map check.
40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
40133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This 'at' value and scratch1 map value are used for tests in both clauses
40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the if.
40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->truncating()) {
40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch3 = ToRegister(instr->TempAt(1));
40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!scratch3.is(input_reg) &&
40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           !scratch3.is(scratch1) &&
40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           !scratch3.is(scratch2));
40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Performs a truncating conversion of a floating point number as used by
40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the JS bitwise operations.
40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label heap_number;
40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&heap_number, eq, scratch1, Operand(at));  // HeapNumber map?
40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for undefined. Undefined is converted to zero for truncating
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // conversions.
40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), input_reg, Operand(at));
40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(ToRegister(instr->result()).is(input_reg));
40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(input_reg, zero_reg);
40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&heap_number);
40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(double_scratch2,
40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitECMATruncate(input_reg,
40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        double_scratch2,
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        single_scratch,
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1,
40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch2,
40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch3);
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Deoptimize if we don't have a heap number.
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at));
40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the double value.
40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(double_scratch,
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register except_flag = scratch2;
40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitFPUTruncate(kRoundToZero,
40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       single_scratch,
40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       double_scratch,
40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       scratch1,
40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       except_flag,
40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       kCheckForInexactConversion);
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Deopt if the operation did not succeed.
40603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
40613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the result.
40633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(input_reg, single_scratch);
40643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&done, ne, input_reg, Operand(zero_reg));
40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mfc1(scratch1, double_scratch.high());
40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
40743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) {
40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredTaggedToI: public LDeferredCode {
40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
40803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
40823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
40833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
40843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
40853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LTaggedToI* instr_;
40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
40873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
40893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(input->IsRegister());
40903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(input->Equals(instr->result()));
40913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(input);
40933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Let the deferred code handle the HeapObject case.
40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfNotSmi(input_reg, deferred->entry());
40983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi to int32 conversion.
41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(input_reg);
41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(input->IsRegister());
41083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
41093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result->IsDoubleRegister());
41103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(input);
41123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result_reg = ToDoubleRegister(result);
41133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitNumberUntagD(input_reg, result_reg,
41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   instr->hydrogen()->deoptimize_on_undefined(),
41163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   instr->hydrogen()->deoptimize_on_minus_zero(),
41173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   instr->environment());
41183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) {
41223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
41243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = ToRegister(instr->TempAt(0));
41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister double_input = ToDoubleRegister(instr->InputAt(0));
41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister single_scratch = double_scratch0().low();
41273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->truncating()) {
41293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch3 = ToRegister(instr->TempAt(1));
41303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitECMATruncate(result_reg,
41313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        double_input,
41323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        single_scratch,
41333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1,
41343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch2,
41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch3);
41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
41373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register except_flag = scratch2;
41383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitFPUTruncate(kRoundToMinusInf,
41403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       single_scratch,
41413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       double_input,
41423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       scratch1,
41433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       except_flag,
41443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       kCheckForInexactConversion);
41453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Deopt if the operation did not succeed (except_flag != 0).
41473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the result.
41503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mfc1(result_reg, single_scratch);
41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
41523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) {
41563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
41573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, ToRegister(input), Operand(kSmiTagMask));
41583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
41593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, ToRegister(input), Operand(kSmiTagMask));
41653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, scratch, scratch);
41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->is_interval_check()) {
41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InstanceType first;
41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InstanceType last;
41783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->GetCheckInterval(&first, &last);
41793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If there is only one type in the interval check for equality.
41813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (first == last) {
41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(ne, instr->environment(), scratch, Operand(first));
41833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(lo, instr->environment(), scratch, Operand(first));
41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Omit check for the last type.
41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (last != LAST_TYPE) {
41873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        DeoptimizeIf(hi, instr->environment(), scratch, Operand(last));
41883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t mask;
41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t tag;
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsPowerOf2(mask)) {
41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(tag == 0 || IsPowerOf2(tag));
41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(at, scratch, mask);
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(tag == 0 ? ne : eq, instr->environment(),
41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          at, Operand(zero_reg));
42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(scratch, scratch, Operand(mask));
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeoptimizeIf(ne, instr->environment(), scratch, Operand(tag));
42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckFunction(LCheckFunction* instr) {
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->value());
42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> target = instr->hydrogen()->target();
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*target)) {
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(instr->value());
42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(target);
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(at, Operand(Handle<Object>(cell)));
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(at, FieldMemOperand(at, JSGlobalPropertyCell::kValueOffset));
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), reg,
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Operand(at));
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne, instr->environment(), reg,
42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Operand(target));
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapCommon(Register reg,
42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Register scratch,
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<Map> map,
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                CompareMapMode mode,
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                LEnvironment* env) {
42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareMapAndBranch(reg, scratch, map, &success, eq, &success, mode);
42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(al, env);
42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&success);
42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMap(LCheckMap* instr) {
42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* input = instr->InputAt(0);
42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(input->IsRegister());
42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(input);
42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> map = instr->hydrogen()->map();
42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   instr->environment());
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0));
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampDoubleToUint8(result_reg, value_reg, temp_reg);
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register unclamped_reg = ToRegister(instr->unclamped());
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampUint8(result_reg, unclamped_reg);
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(instr->unclamped());
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0));
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_smi, done, heap_number;
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both smi and heap number cases are handled.
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi);
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for heap number
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map()));
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for undefined. Undefined is converted to zero for clamping
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // conversions.
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), input_reg,
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Operand(factory()->undefined_value()));
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result_reg, zero_reg);
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&heap_number);
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldc1(double_scratch0(), FieldMemOperand(input_reg,
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             HeapNumber::kValueOffset));
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&is_smi);
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampUint8(result_reg, scratch);
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp1 = ToRegister(instr->TempAt(0));
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp2 = ToRegister(instr->TempAt(1));
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> holder = instr->holder();
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current_prototype = instr->prototype();
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load prototype object.
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(temp1, current_prototype);
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check prototype maps up to the holder.
43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current_prototype.is_identical_to(holder)) {
43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoCheckMapCommon(temp1, temp2,
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Handle<Map>(current_prototype->map()),
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current_prototype =
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load next prototype object.
43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(temp1, current_prototype);
43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the holder map.
43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoCheckMapCommon(temp1, temp2,
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Handle<Map>(current_prototype->map()),
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAllocateObject(LAllocateObject* instr) {
43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredAllocateObject: public LDeferredCode {
43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LAllocateObject* instr_;
43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr);
43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = ToRegister(instr->TempAt(0));
43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = ToRegister(instr->TempAt(1));
43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> constructor = instr->hydrogen()->constructor();
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> initial_map(constructor->initial_map());
43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int instance_size = initial_map->instance_size();
43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(initial_map->pre_allocated_property_fields() +
43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         initial_map->unused_property_fields() -
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         initial_map->inobject_properties() == 0);
43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate memory for the object.  The initial map might change when
43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the constructor's prototype changes, but instance size and property
43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // counts remain unchanged (if slack tracking finished).
43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(instance_size,
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        result,
43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch,
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch2,
43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        deferred->entry(),
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        TAG_OBJECT);
43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the initial map.
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = scratch;
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(map, constructor);
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Initialize map and fields of the newly allocated object.
43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(map, FieldMemOperand(result, JSObject::kMapOffset));
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_map->inobject_properties() != 0) {
43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < initial_map->inobject_properties(); i++) {
43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int property_offset = JSObject::kHeaderSize + i * kPointerSize;
43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(scratch, FieldMemOperand(result, property_offset));
43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> constructor = instr->hydrogen()->constructor();
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(a0, constructor);
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(a0);
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr);
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap = isolate()->heap();
44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind boilerplate_elements_kind =
44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->hydrogen()->boilerplate_elements_kind();
44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deopt if the array literal boilerplate ElementsKind is of a type different
44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // than the expected one. The check isn't necessary if the boilerplate has
44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // already been converted to FAST_ELEMENTS.
44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (boilerplate_elements_kind != FAST_ELEMENTS) {
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(a1, instr->hydrogen()->boilerplate_object());
44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load map into a2.
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the map's "bit field 2".
44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(a2, FieldMemOperand(a2, Map::kBitField2Offset));
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Retrieve elements_kind from bit field 2.
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ext(a2, a2, Map::kElementsKindShift, Map::kElementsKindBitCount);
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeoptimizeIf(ne,
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 instr->environment(),
44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 a2,
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Operand(boilerplate_elements_kind));
44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Boilerplate already exists, constant elements are never accessed.
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pass an empty fixed array.
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a1, Operand(Handle<FixedArray>(heap->empty_fixed_array())));
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(a3, a2, a1);
44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pick the right runtime function or stub to call.
44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = instr->hydrogen()->length();
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->IsCopyOnWrite()) {
44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(instr->hydrogen()->depth() == 1);
44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub::Mode mode =
44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub stub(mode, length);
44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (instr->hydrogen()->depth() > 1) {
44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub::Mode mode =
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            : FastCloneShallowArrayStub::CLONE_ELEMENTS;
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub stub(mode, length);
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitDeepCopy(Handle<JSObject> object,
44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register result,
44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register source,
44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            int* offset) {
44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!source.is(a2));
44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!result.is(a2));
44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only elements backing stores for non-COW arrays need to be copied.
44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> elements(object->elements());
44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_elements = elements->length() > 0 &&
44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements->map() != isolate()->heap()->fixed_cow_array_map();
44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increase the offset so that subsequent objects end up right after
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // this object and its backing store.
44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int object_offset = *offset;
44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int object_size = object->map()->instance_size();
44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int elements_offset = *offset + object_size;
44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int elements_size = has_elements ? elements->Size() : 0;
44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *offset += object_size + elements_size;
44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy object header.
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(object->properties()->length() == 0);
44753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int inobject_properties = object->map()->inobject_properties();
44763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int header_size = object_size - inobject_properties * kPointerSize;
44773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < header_size; i += kPointerSize) {
44783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (has_elements && i == JSObject::kElementsOffset) {
44793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a2, result, Operand(elements_offset));
44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a2, FieldMemOperand(source, i));
44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a2, FieldMemOperand(result, object_offset + i));
44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy in-object properties.
44873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < inobject_properties; i++) {
44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int total_offset = object_offset + object->GetInObjectPropertyOffset(i);
44893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i));
44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (value->IsJSObject()) {
44913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a2, result, Operand(*offset));
44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, FieldMemOperand(result, total_offset));
44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadHeapObject(source, value_object);
44953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitDeepCopy(value_object, result, source, offset);
44963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (value->IsHeapObject()) {
44973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadHeapObject(a2, Handle<HeapObject>::cast(value));
44983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, FieldMemOperand(result, total_offset));
44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a2, Operand(value));
45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, FieldMemOperand(result, total_offset));
45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_elements) {
45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy elements backing store header.
45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadHeapObject(source, elements);
45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) {
45103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a2, FieldMemOperand(source, i));
45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, FieldMemOperand(result, elements_offset + i));
45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy elements backing store content.
45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int elements_length = has_elements ? elements->length() : 0;
45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (elements->IsFixedDoubleArray()) {
45173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<FixedDoubleArray> double_array =
45183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<FixedDoubleArray>::cast(elements);
45193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < elements_length; i++) {
45203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int64_t value = double_array->get_representation(i);
45213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We only support little endian mode...
45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int32_t value_low = value & 0xFFFFFFFF;
45233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int32_t value_high = value >> 32;
45243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int total_offset =
45253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
45263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ li(a2, Operand(value_low));
45273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(a2, FieldMemOperand(result, total_offset));
45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ li(a2, Operand(value_high));
45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(a2, FieldMemOperand(result, total_offset + 4));
45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
45313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (elements->IsFixedArray()) {
45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < elements_length; i++) {
45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<Object> value = JSObject::GetElement(object, i);
45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (value->IsJSObject()) {
45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Addu(a2, result, Operand(*offset));
45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sw(a2, FieldMemOperand(result, total_offset));
45393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadHeapObject(source, value_object);
45403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          EmitDeepCopy(value_object, result, source, offset);
45413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (value->IsHeapObject()) {
45423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadHeapObject(a2, Handle<HeapObject>::cast(value));
45433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sw(a2, FieldMemOperand(result, total_offset));
45443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
45453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ li(a2, Operand(value));
45463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sw(a2, FieldMemOperand(result, total_offset));
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
45483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
45513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
45533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoFastLiteral(LFastLiteral* instr) {
45573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int size = instr->hydrogen()->total_size();
45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate all objects that are part of the literal in one big
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allocation. This avoids multiple limit checks.
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label allocated, runtime_allocate;
45623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
45633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&allocated);
45643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&runtime_allocate);
45663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a0, Operand(Smi::FromInt(size)));
45673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(a0);
45683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
45693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&allocated);
45713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int offset = 0;
45723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(a1, instr->hydrogen()->boilerplate());
45733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitDeepCopy(instr->hydrogen()->boilerplate(), v0, a1, &offset);
45743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(size, offset);
45753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
45793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
45803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> literals(instr->environment()->closure()->literals());
45813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties =
45823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->hydrogen()->constant_properties();
45833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the parameters to the stub/runtime call.
45853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(t0, literals);
45863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a3, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
45873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, Operand(constant_properties));
45883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int flags = instr->hydrogen()->fast_elements()
45893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? ObjectLiteral::kFastElements
45903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ObjectLiteral::kNoFlags;
45913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a1, Operand(Smi::FromInt(flags)));
45923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(t0, a3, a2, a1);
45933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pick the right runtime function or stub to call.
45953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->depth() > 1) {
45973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
45983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (flags != ObjectLiteral::kFastElements ||
45993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
46003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
46013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
46023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowObjectStub stub(properties_count);
46033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
46043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) {
46093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->InputAt(0)).is(a0));
46103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
46113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(a0);
46123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kToFastProperties, 1, instr);
46133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
46173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialized;
46183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Registers will be used as follows:
46193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a3 = JS function.
46203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // t3 = literals array.
46213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a1 = regexp literal.
46223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a0 = regexp literal clone.
46233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a2 and t0-t2 are used as temporaries.
46243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
46253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(t3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literal_offset = FixedArray::kHeaderSize +
46273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->hydrogen()->literal_index() * kPointerSize;
46283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a1, FieldMemOperand(t3, literal_offset));
46293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
46303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&materialized, ne, a1, Operand(at));
46313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create regexp literal using runtime function
46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Result will be in v0.
46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t1, Operand(instr->hydrogen()->pattern()));
46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(instr->hydrogen()->flags()));
46373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(t3, t2, t1, t0);
46383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(a1, v0);
46403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&materialized);
46423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
46433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label allocated, runtime_allocate;
46443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
46463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&allocated);
46473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&runtime_allocate);
46493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a0, Operand(Smi::FromInt(size)));
46503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(a1, a0);
46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
46523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(a1);
46533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&allocated);
46553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy the content into the newly allocated memory.
46563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (Unroll copy loop once for better throughput).
46573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
46583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a3, FieldMemOperand(a1, i));
46593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a2, FieldMemOperand(a1, i + kPointerSize));
46603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a3, FieldMemOperand(v0, i));
46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a2, FieldMemOperand(v0, i + kPointerSize));
46623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
46643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a3, FieldMemOperand(a1, size - kPointerSize));
46653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a3, FieldMemOperand(v0, size - kPointerSize));
46663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
46713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the fast case closure allocation code that allocates in new
46723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // space for nested functions that don't need literals cloning.
46733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared_info = instr->shared_info();
46743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool pretenure = instr->hydrogen()->pretenure();
46753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!pretenure && shared_info->num_literals() == 0) {
46763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastNewClosureStub stub(shared_info->language_mode());
46773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a1, Operand(shared_info));
46783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
46793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
46803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
46813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a2, Operand(shared_info));
46823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a1, Operand(pretenure
46833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       ? factory()->true_value()
46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       : factory()->false_value()));
46853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(cp, a2, a1);
46863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kNewClosure, 3, instr);
46873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) {
46923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ToRegister(instr->result()).is(v0));
46933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
46943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(input);
46953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kTypeof, 1, instr);
46963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
47003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input = ToRegister(instr->InputAt(0));
47013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
47023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* true_label = chunk_->GetAssemblyLabel(true_block);
47043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* false_label = chunk_->GetAssemblyLabel(false_block);
47053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register cmp1 = no_reg;
47073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cmp2 = Operand(no_reg);
47083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition final_branch_condition = EmitTypeofIs(true_label,
47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  false_label,
47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  input,
47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  instr->type_literal(),
47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  cmp1,
47143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  cmp2);
47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(cmp1.is_valid());
47173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid());
47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (final_branch_condition != kNoCondition) {
47203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitBranch(true_block, false_block, final_branch_condition, cmp1, cmp2);
47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitTypeofIs(Label* true_label,
47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* false_label,
47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register input,
47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Handle<String> type_name,
47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register& cmp1,
47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Operand& cmp2) {
47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This function utilizes the delay slot heavily. This is used to load
47323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // values that are always usable without depending on the type of the input
47333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // register.
47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition final_branch_condition = kNoCondition;
47353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
47363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (type_name->Equals(heap()->number_symbol())) {
47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, true_label);
47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
47393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
47403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = input;
47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(at);
47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (type_name->Equals(heap()->string_symbol())) {
47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
47463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, input, scratch);
47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, false_label,
47483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              ge, scratch, Operand(FIRST_NONSTRING_TYPE));
47493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // input is an object so we can load the BitFieldOffset even if we take the
47503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // other branch.
47513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
47523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(at, at, 1 << Map::kIsUndetectable);
47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
47543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(zero_reg);
47553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
47563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (type_name->Equals(heap()->boolean_symbol())) {
47583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTrueValueRootIndex);
47593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
47603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kFalseValueRootIndex);
47613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
47623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(input);
47633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
47643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
47663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kNullValueRootIndex);
47673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
47683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(input);
47693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
47703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (type_name->Equals(heap()->undefined_symbol())) {
47723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
47733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
47743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The first instruction of JumpIfSmi is an And - it is safe in the delay
47753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // slot.
47763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
47773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for undetectable objects => true.
47783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
47793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
47803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(at, at, 1 << Map::kIsUndetectable);
47813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
47823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(zero_reg);
47833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = ne;
47843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (type_name->Equals(heap()->function_symbol())) {
47863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
47873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
47883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, scratch, input);
47893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(true_label, eq, input, Operand(JS_FUNCTION_TYPE));
47903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = input;
47913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(JS_FUNCTION_PROXY_TYPE);
47923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
47933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (type_name->Equals(heap()->object_symbol())) {
47953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
47963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!FLAG_harmony_typeof) {
47973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(at, Heap::kNullValueRootIndex);
47983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
47993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
48003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // input is an object, it is safe to use GetObjectType in the delay slot.
48013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, input, scratch);
48023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, false_label,
48033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
48043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Still an object, so the InstanceType can be loaded.
48053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(scratch, FieldMemOperand(input, Map::kInstanceTypeOffset));
48063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, false_label,
48073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
48083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Still an object, so the BitField can be loaded.
48093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for undetectable objects => false.
48103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
48113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(at, at, 1 << Map::kIsUndetectable);
48123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
48133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(zero_reg);
48143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
48153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
48173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp1 = at;
48183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp2 = Operand(zero_reg);  // Set to valid regs, to avoid caller assertion.
48193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(false_label);
48203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
48213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return final_branch_condition;
48233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
48273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp1 = ToRegister(instr->TempAt(0));
48283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int true_block = chunk_->LookupDestination(instr->true_block_id());
48293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int false_block = chunk_->LookupDestination(instr->false_block_id());
48303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitIsConstructCall(temp1, scratch0());
48323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitBranch(true_block, false_block, eq, temp1,
48343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
48353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
48393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!temp1.is(temp2));
48403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the frame pointer for the calling frame.
48413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
48423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip the arguments adaptor frame if it exists.
48443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_frame_marker;
48453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
48463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&check_frame_marker, ne, temp2,
48473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
48483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
48493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the marker in the calling frame.
48513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_frame_marker);
48523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
48533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt() {
48573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Ensure that we have enough space after the previous lazy-bailout
48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instruction for patching the code here.
48593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int current_pc = masm()->pc_offset();
48603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int patch_size = Deoptimizer::patch_size();
48613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (current_pc < last_lazy_deopt_pc_ + patch_size) {
48623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
48633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
48643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while (padding_size > 0) {
48653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ nop();
48663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      padding_size -= Assembler::kInstrSize;
48673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
48683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
48693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  last_lazy_deopt_pc_ = masm()->pc_offset();
48703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) {
48743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EnsureSpaceForLazyDeopt();
48753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasEnvironment());
48763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
48773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
48783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
48793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) {
48833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg));
48843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
48883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
48893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = ToRegister(instr->key());
48903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register strict = scratch0();
48913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(strict, Operand(Smi::FromInt(strict_mode_flag())));
48923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(object, key, strict);
48933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
48943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
48953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
48963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator safepoint_generator(
48973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      this, pointers, Safepoint::kLazyDeopt);
48983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
48993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIn(LIn* instr) {
49033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register obj = ToRegister(instr->object());
49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = ToRegister(instr->key());
49053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(key, obj);
49063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
49073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
49083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordPosition(pointers->position());
49093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
49103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
49113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
49153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
49163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
49173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(
49183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
49193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasEnvironment());
49203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
49213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
49223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) {
49263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class DeferredStackCheck: public LDeferredCode {
49273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
49283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
49293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
49303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
49313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    virtual LInstruction* instr() { return instr_; }
49323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
49333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStackCheck* instr_;
49343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
49353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(instr->HasEnvironment());
49373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
49383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There is no LLazyBailout instruction for stack-checks. We have to
49393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // prepare for lazy deoptimization explicitly here.
49403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->is_function_entry()) {
49413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Perform stack overflow check.
49423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
49433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kStackLimitRootIndex);
49443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, hs, sp, Operand(at));
49453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StackCheckStub stub;
49463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
49473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EnsureSpaceForLazyDeopt();
49483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
49493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
49503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
49513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
49523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(instr->hydrogen()->is_backwards_branch());
49533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Perform stack overflow check if this goto needs it before jumping.
49543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStackCheck* deferred_stack_check =
49553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new DeferredStackCheck(this, instr);
49563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kStackLimitRootIndex);
49573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at));
49583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EnsureSpaceForLazyDeopt();
49593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(instr->done_label());
49603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    deferred_stack_check->SetExit(instr->done_label());
49613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
49623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Don't record a deoptimization index for the safepoint here.
49633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // This will be done explicitly when emitting call and the safepoint in
49643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the deferred code.
49653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
49663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) {
49703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is a pseudo-instruction that ensures that the environment here is
49713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // properly registered for deoptimization and records the assembler's PC
49723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // offset.
49733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* environment = instr->environment();
49743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
49753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   instr->SpilledDoubleRegisterArray());
49763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the environment were already registered, we would have no way of
49783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // backpatching it with the spill slot operands.
49793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!environment->HasBeenRegistered());
49803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
49813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(osr_pc_offset_ == -1);
49823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  osr_pc_offset_ = masm()->pc_offset();
49833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
49873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
49883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
49893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
49903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), object, Operand(at));
49913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register null_value = t1;
49933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
49943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), object, Operand(null_value));
49953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, object, kSmiTagMask);
49973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
49983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
50003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(object, a1, a1);
50013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(le, instr->environment(), a1, Operand(LAST_JS_PROXY_TYPE));
50023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label use_cache, call_runtime;
50043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(object.is(a0));
50053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(null_value, &call_runtime);
50063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset));
50083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&use_cache);
50093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the set of properties to enumerate.
50113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&call_runtime);
50123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(object);
50133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
50143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
50163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result.is(v0));
50173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kMetaMapRootIndex);
50183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), a1, Operand(at));
50193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&use_cache);
50203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
50243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ToRegister(instr->map());
50253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
50263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadInstanceDescriptors(map, result);
50273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
50283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(result, DescriptorArray::kEnumerationIndexOffset));
50293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
50303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
50313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
50323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
50363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->value());
50373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ToRegister(instr->map());
50383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
50393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0()));
50403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
50443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
50453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register index = ToRegister(instr->index());
50463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
50473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
50483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label out_of_object, done;
50503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg));
50513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, index, kPointerSizeLog2 - kSmiTagSize);  // In delay slot.
50523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
50543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, object, scratch);
50553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
50563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
50583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&out_of_object);
50603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
50613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Index is equal to negated out of object property index plus 1.
50623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(scratch, result, scratch);
50633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(scratch,
50643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                FixedArray::kHeaderSize - kPointerSize));
50653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
50663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __
50703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} }  // namespace v8::internal
5072