13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implementation.
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      allow_stub_calls_(true),
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false) {
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (isolate() != NULL) {
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                  isolate());
528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InNewSpace(
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(cc == equal || cc == not_equal);
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that we can use a test_b.
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(MemoryChunk::IN_FROM_SPACE < 8);
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(MemoryChunk::IN_TO_SPACE < 8);
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int mask = (1 << MemoryChunk::IN_FROM_SPACE)
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           | (1 << MemoryChunk::IN_TO_SPACE);
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If non-zero, the page belongs to new-space.
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         static_cast<uint8_t>(mask));
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,  // Only used for debug checks.
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register addr,
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler::RememberedSetFinalAction and_then) {
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference store_buffer =
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::store_buffer_top(isolate());
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand::StaticVariable(store_buffer));
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(scratch, 0), addr);
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch, Immediate(kPointerSize));
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(store_buffer), scratch);
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(not_equal, &buffer_overflowed, Label::kNear);
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(and_then == kFallThroughAtEnd);
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &done, Label::kNear);
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StoreBufferOverflowStub store_buffer_overflow =
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreBufferOverflowStub(save_fp);
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(and_then == kFallThroughAtEnd);
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister scratch_reg,
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Register result_reg) {
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference zero_ref = ExternalReference::address_of_zero();
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movdbl(scratch_reg, Operand::StaticVariable(zero_ref));
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, Immediate(0));
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ucomisd(input_reg, scratch_reg);
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(below, &done, Label::kNear);
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference half_ref = ExternalReference::address_of_one_half();
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movdbl(scratch_reg, Operand::StaticVariable(half_ref));
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  addsd(scratch_reg, input_reg);
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cvttsd2si(result_reg, Operand(scratch_reg));
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(result_reg, Immediate(0xFFFFFF00));
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, Immediate(255));
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  test(reg, Immediate(0xFFFFFF00));
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  dec_b(reg);  // 0 if negative, 255 if positive.
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteArray(Register object,
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register value,
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register index,
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      SaveFPRegsMode save_fp,
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      RememberedSetAction remembered_set_action,
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      SmiCheck smi_check) {
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(0, kSmiTag);
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(value, Immediate(kSmiTagMask));
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &done);
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address in the same manner as
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // into an array of words.
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, Operand(object, index, times_half_pointer_size,
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(value, Immediate(BitCast<int32_t>(kZapValue)));
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(index, Immediate(BitCast<int32_t>(kZapValue)));
192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck smi_check) {
2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip barrier if writing a smi.
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsAligned(offset, kPointerSize));
216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(dst, FieldOperand(object, offset));
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test_b(dst, (1 << kPointerSizeLog2) - 1);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
22485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWrite(
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
2324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(value, Immediate(BitCast<int32_t>(kZapValue)));
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(dst, Immediate(BitCast<int32_t>(kZapValue)));
2364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2408defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object,
2418defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register address,
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register value,
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SaveFPRegsMode fp_mode,
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 RememberedSetAction remembered_set_action,
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 SmiCheck smi_check) {
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is(value));
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is(address));
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!value.is(address));
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AbortIfSmi(object);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(value, Operand(address, 0));
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
2678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
2698defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done, Label::kNear);
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(value,
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
2908defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2918defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
2928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
2948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2968defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(address, Immediate(BitCast<int32_t>(kZapValue)));
2978defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(value, Immediate(BitCast<int32_t>(kZapValue)));
2988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
2998defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
3008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3018defd9ff6930b4e24729971a61cf7469daf119beSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Set(eax, Immediate(0));
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, const Immediate& x) {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x.is_zero()) {
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(dst, dst);  // Shorter than mov.
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(dst, x);
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, const Immediate& x) {
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(dst, x);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
327053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  static const int kMaxImmediateBits = 17;
328053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (x.rmode_ != RelocInfo::NONE) return false;
329053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return !is_intn(x.x_, kMaxImmediateBits);
330053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
331053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
332053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
333053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafeSet(Register dst, const Immediate& x) {
334053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
335053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    Set(dst, Immediate(x.x_ ^ jit_cookie()));
336053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(dst, jit_cookie());
337053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
338053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    Set(dst, x);
339053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
340053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
341053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
342053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
343053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockvoid MacroAssembler::SafePush(const Immediate& x) {
344053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
345053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(Immediate(x.x_ ^ jit_cookie()));
346053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    xor_(Operand(esp, 0), Immediate(jit_cookie()));
347053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
348053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    push(x);
349053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
350053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block}
351053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
352053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
35369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
35469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // see ROOT_ACCESSOR macro in factory.h
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(with, value);
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareRoot(const Operand& with,
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Heap::RootListIndex index) {
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // see ROOT_ACCESSOR macro in factory.h
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  cmp(with, value);
365c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
366c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       static_cast<int8_t>(type));
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Map::kMaximumBitField2FastElementValue);
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 1);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Map::kMaximumBitField2FastSmiOnlyElementValue);
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch       Map::kMaximumBitField2FastElementValue);
4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(above, fail, distance);
4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastSmiOnlyElements(Register map,
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Label* fail,
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Label::Distance distance) {
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Map::kMaximumBitField2FastSmiOnlyElementValue);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register key,
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch1,
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister scratch2,
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* fail,
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool specialize_for_processor) {
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value;
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double value, canonicalize NaN.
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(maybe_number, offset),
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Immediate(kNaNOrInfinityLowerBoundUpper32));
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(greater_equal, &maybe_nan, Label::kNear);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_nan);
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference canonical_nan_reference =
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference::address_of_canonical_non_hole_nan();
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope use_sse2(SSE2);
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&have_double_value);
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize),
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch2);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset));
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&have_double_value);
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize));
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&done);
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&maybe_nan);
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it's an Infinity, and the non-NaN code path applies.
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(greater, &is_nan, Label::kNear);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &not_nan);
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_nan);
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope use_sse2(SSE2);
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference));
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fld_d(Operand::StaticVariable(canonical_nan_reference));
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&have_double_value, Label::kNear);
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. Convert to a double and store.
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, maybe_number);
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(scratch1);
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CpuFeatures::Scope fscope(SSE2);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cvtsi2sd(scratch2, scratch1);
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize),
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch2);
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(scratch1);
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fild_s(Operand(esp, 0));
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pop(scratch1);
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize));
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CompareMap(Register obj,
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<Map> map,
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label* early_success,
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                CompareMapMode mode) {
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_fast_element_map(
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_fast_element_map == NULL ||
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() != FAST_ELEMENTS);
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_fast_element_map != NULL) {
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      j(equal, early_success, Label::kNear);
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(FieldOperand(obj, HeapObject::kMapOffset),
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Map>(transitioned_fast_element_map));
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* transitioned_double_map(
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(transitioned_double_map == NULL ||
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_double_map != NULL) {
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      j(equal, early_success, Label::kNear);
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(FieldOperand(obj, HeapObject::kMapOffset),
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Map>(transitioned_double_map));
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
5203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
5213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              SmiCheckType smi_check_type,
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              CompareMapMode mode) {
524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, fail);
5263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label success;
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareMap(obj, map, &success, mode);
5303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&success);
5323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj,
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Map> map,
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Code> success,
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SmiCheckType smi_check_type) {
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success);
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register map,
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register instance_type) {
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
55569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  test(instance_type, Immediate(kIsNotStringMask));
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::IsObjectJSObjectType(Register heap_object,
5627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          Register map,
5637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          Register scratch,
5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          Label* fail) {
5657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
5667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  IsInstanceJSObjectType(map, scratch, fail);
5677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
5687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::IsInstanceJSObjectType(Register map,
5717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Register scratch,
5727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Label* fail) {
5737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  cmp(scratch,
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  j(above, fail);
5787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
5797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
5828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(CMOV)) {
5833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    fucomip();
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    fstp(0);
5853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    fucompp();
5873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    push(eax);
5883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    fnstsw_ax();
5893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sahf();
5903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    pop(eax);
5913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::AbortIfNotNumber(Register object) {
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label ok;
5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(object, &ok);
598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  cmp(FieldOperand(object, HeapObject::kMapOffset),
59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->heap_number_map());
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Assert(equal, "Operand not a number");
601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  bind(&ok);
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::AbortIfNotSmi(Register object) {
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  test(object, Immediate(kSmiTagMask));
607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(equal, "Operand is not a smi");
608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::AbortIfNotString(Register object) {
61280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  test(object, Immediate(kSmiTagMask));
61380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Assert(not_equal, "Operand is not a string");
61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  push(object);
61580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(object, FieldOperand(object, HeapObject::kMapOffset));
61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CmpInstanceType(object, FIRST_NONSTRING_TYPE);
61780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  pop(object);
61880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Assert(below, "Operand is not a string");
61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
622756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  test(object, Immediate(kSmiTagMask));
624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(not_equal, "Operand is a smi");
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(esi);
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(Smi::FromInt(type)));
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(CodeObject()));
63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "code object not properly patched");
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(Smi::FromInt(type)));
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "stack frame types must match");
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  leave();
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
65180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue() {
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ebp);
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebp, esp);
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kSPOffset  == -1 * kPointerSize);
661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress,
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    isolate());
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), esi);
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all XMM registers.
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CpuFeatures::Scope scope(SSE2);
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize;
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(space));
6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const int offset = -2 * kPointerSize;
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(argc * kPointerSize));
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kFrameAlignment = OS::ActivationFrameAlignment();
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(IsPowerOf2(kFrameAlignment));
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(esp, -kFrameAlignment);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::EnterExitFrame(bool save_doubles) {
70280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argc and argv in callee-saved registers.
705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edi, eax);
707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  lea(esi, Operand(ebp, eax, times_4, offset));
708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Reserve space for argc, argv and isolate.
71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  EnterExitFrameEpilogue(3, save_doubles);
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int argc) {
71580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue();
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EnterExitFrameEpilogue(argc, false);
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles) {
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all XMM registers.
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CpuFeatures::Scope scope(SSE2);
7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const int offset = -2 * kPointerSize;
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      XMMRegister reg = XMMRegister::from_code(i);
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      movdbl(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the return address from the stack and restore the frame pointer.
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ecx, Operand(ebp, 1 * kPointerSize));
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebp, Operand(ebp, 0 * kPointerSize));
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop the arguments and the receiver from the caller stack.
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  lea(esp, Operand(esi, 1 * kPointerSize));
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Push the return address to get ready to return.
7398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  push(ecx);
7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
7428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
7438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveExitFrameEpilogue() {
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, Operand::StaticVariable(context_address));
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(context_address), Immediate(0));
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LeaveApiExitFrame() {
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, ebp);
7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  pop(ebp);
7628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveExitFrameEpilogue();
7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind,
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int handler_index) {
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
77169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We will build up the handler from the bottom by pushing on the stack.
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First push the frame pointer and context.
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (kind == StackHandler::JS_ENTRY) {
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The frame pointer does not point to a JS frame so we save NULL for
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ebp. We expect the code throwing an exception to check ebp before
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // dereferencing it to restore the context.
78385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    push(Immediate(0));  // NULL frame pointer.
78485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    push(Immediate(Smi::FromInt(0)));  // No context.
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(ebp);
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(esi);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the state and the code object.
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned state =
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::IndexField::encode(handler_index) |
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StackHandler::KindField::encode(kind);
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Immediate(state));
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(CodeObject());
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  push(Operand::StaticVariable(handler_address));
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand::StaticVariable(handler_address), esp);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
80569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpToHandlerEntry() {
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the handler entry address and jump to it.  The handler table is
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a fixed array of (smi-tagged) code offsets.
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // eax = exception, edi = code object, edx = state.
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset));
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(edx, StackHandler::kKindWidth);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize));
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiUntag(edx);
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(edi);
822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) {
826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust this code if not the case.
82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
82869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in eax.
835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(eax)) {
836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(eax, value);
837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top handler.
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
84085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  mov(esp, Operand::StaticVariable(handler_address));
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore the next handler.
84285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  pop(Operand::StaticVariable(handler_address));
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remove the code object and state, compute the handler address in edi.
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(edi);  // Code object.
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(edx);  // Index and state.
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore the context and frame pointer.
84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(esi);  // Context.
85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  pop(ebp);  // Frame pointer.
851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
85269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // If the handler is a JS frame, restore the context to the frame.
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ebp or esi.
855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(esi, esi);
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &skip, Label::kNear);
85869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&skip);
860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::ThrowUncatchable(Register value) {
866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust this code if not the case.
86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
86869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The exception is expected in eax.
8755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!value.is(eax)) {
876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    mov(eax, value);
877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Drop the stack pointer to the top of the top stack handler.
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
88085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  mov(esp, Operand::StaticVariable(handler_address));
881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Unwind the handlers until the top ENTRY handler is found.
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fetch_next, check_kind;
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&check_kind, Label::kNear);
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&fetch_next);
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
887592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_kind);
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(Operand(esp, StackHandlerConstants::kStateOffset),
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate(StackHandler::KindField::kMask));
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, &fetch_next);
89385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set the top handler address to next handler past the top ENTRY handler.
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(Operand::StaticVariable(handler_address));
89685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remove the code object and state, compute the handler address in edi.
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(edi);  // Code object.
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(edx);  // Index and state.
900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clear the context pointer and frame pointer (0 was saved in the handler).
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  pop(esi);
903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(ebp);
904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpToHandlerEntry();
906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset));
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
92044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(scratch, Immediate(0));
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "we should not have an empty lexical context");
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, FieldOperand(scratch, offset));
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
93044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(scratch);
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map.
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(scratch, isolate()->factory()->global_context_map());
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(scratch);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, &same_contexts);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens, save holder_reg on the stack so we can use it
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as a temporary register.
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(119): avoid push(holder_reg)/pop(holder_reg)
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(holder_reg);
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(holder_reg, isolate()->factory()->null_value());
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "JSGlobalProxy::context() should not be null.");
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map(),
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmp(holder_reg, isolate()->factory()->global_context_map());
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int token_offset = Context::kHeaderSize +
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, FieldOperand(scratch, token_offset));
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(scratch, FieldOperand(holder_reg, token_offset));
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pop(holder_reg);
971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, miss);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
977c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Compute the hash code from the untagged key.  This must be kept in sync
978c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// with ComputeIntegerHash in utils.h.
979c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch//
980c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Note: r0 will contain hash code
981c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
982c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
983c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (Serializer::enabled()) {
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
986c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
989c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SmiUntag(scratch);
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, scratch);
991c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else {
992c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int32_t seed = isolate()->heap()->HashSeed();
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(r0, Immediate(seed));
994c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
995c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
996c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
997c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
998c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  not_(r0);
999c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shl(scratch, 15);
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(r0, scratch);
1001c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
1002c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1003c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 12);
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1005c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
1006c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  lea(r0, Operand(r0, r0, times_4, 0));
1007c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
1008c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1009c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 4);
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1011c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
1012c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imul(r0, r0, 2057);
1013c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
1014c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(scratch, r0);
1015c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shr(scratch, 16);
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(r0, scratch);
1017c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
1018c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1019c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
1020c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
10213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
10223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
10233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
10243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
10253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
10273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
10283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
10293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver and is unchanged.
10313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry and is unchanged.
10333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
10353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
10373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
10393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
10413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
10423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeds and we fall through.
10433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
10453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1046c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
1049c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset));
10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  shr(r1, kSmiTagSize);  // convert smi to int
10513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  dec(r1);
10523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kProbes = 4;
10553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kProbes; i++) {
10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(r2, r0);
10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
10593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(r2, r1);
10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
1065c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    ASSERT(SeededNumberDictionary::kEntrySize == 3);
10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
10673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
10693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(key, FieldOperand(elements,
10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          r2,
10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          times_pointer_size,
1072c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                          SeededNumberDictionary::kElementsStartOffset));
10733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i != (kProbes - 1)) {
10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
10753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
10773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
10783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
10793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
10813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the value is a normal propety.
10823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
1083c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT_EQ(NORMAL, 0);
10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
1086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
10873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
10883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
10903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
1091c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
10923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
10933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
10943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(scratch.is(no_reg));
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmp(result, Operand::StaticVariable(new_space_allocation_top));
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "Unexpected allocation top");
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move address of new object to result. Use scratch register if available.
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand::StaticVariable(new_space_allocation_top));
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(new_space_allocation_top));
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result, Operand(scratch, 0));
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               Register scratch) {
112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    test(result_end, Immediate(kObjectAlignmentMask));
1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(zero, "Unaligned allocation in new space");
1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top. Use scratch if available.
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scratch.is(no_reg)) {
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(new_space_allocation_top), result_end);
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand(scratch, 0), result_end);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
11495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
11515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
11525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
11535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
11545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(result_end, Immediate(0x7191));
11555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
11565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
11575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
11585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
11595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
11605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
11615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
11625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
11668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register top_reg = result_end.is_valid() ? result_end : result;
1169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(top_reg, result);
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(top_reg, Immediate(object_size));
1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(carry, gc_required);
1179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1183bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  UpdateAllocationTopHelper(top_reg, scratch);
1184bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1185bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Tag result if requested.
1186bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (top_reg.is(result)) {
1187bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if ((flags & TAG_OBJECT) != 0) {
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sub(result, Immediate(object_size - kHeapObjectTag));
1189bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    } else {
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sub(result, Immediate(object_size));
1191bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1192bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else if ((flags & TAG_OBJECT) != 0) {
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(result, Immediate(kHeapObjectTag));
1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size,
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        ScaleFactor element_size,
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register element_count,
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
12065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
12085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
12095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
12105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
12115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
12125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
12135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
12145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Register element_count is not modified by the function.
12155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
12165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
12175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
12185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
12228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
12271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We assume that element_count*element_size + header_size does not
12291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // overflow.
12301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  lea(result_end, Operand(element_count, element_size, header_size));
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag result if requested.
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    lea(result, Operand(result, kHeapObjectTag));
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UpdateAllocationTopHelper(result_end, scratch);
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
12525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
12545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
12555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Immediate(0x7091));
12565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result_end, Immediate(0x7191));
12575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
12585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        mov(scratch, Immediate(0x7291));
12595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
12605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
12615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
12625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
12635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
12645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
12688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(result_end, object_size);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(result_end, result);
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(carry, gc_required);
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above, gc_required);
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag result if requested.
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    lea(result, Operand(result, kHeapObjectTag));
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Update allocation top.
1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UpdateAllocationTopHelper(result_end, scratch);
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(object, Immediate(~kHeapObjectTagMask));
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(object, Operand::StaticVariable(new_space_allocation_top));
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(below, "Undo allocation of non allocated memory");
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(Operand::StaticVariable(new_space_allocation_top), object);
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch1,
13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch2,
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Label* gc_required) {
13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  AllocateInNewSpace(HeapNumber::kSize,
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     result,
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch1,
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch2,
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     gc_required,
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     TAG_OBJECT);
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->heap_number_map()));
13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateTwoByteString(Register result,
1324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register length,
1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch1,
1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch2,
1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Register scratch3,
1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           Label* gc_required) {
1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(kShortSize == 2);
1333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate two byte string in new space.
1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     times_1,
1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch1,
1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     result,
1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch2,
1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch3,
1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     gc_required,
1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     TAG_OBJECT);
1346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->string_map()));
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiString(Register result,
1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register length,
1360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register scratch1,
1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register scratch2,
1362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Register scratch3,
1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                         Label* gc_required) {
1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Calculate the number of bytes needed for the characters in the string while
1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // observing object alignment.
1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
1367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(scratch1, length);
1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(kCharSize == 1);
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(scratch1, Immediate(kObjectAlignmentMask));
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, Immediate(~kObjectAlignmentMask));
1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate ASCII string in new space.
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AllocateInNewSpace(SeqAsciiString::kHeaderSize,
1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     times_1,
1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch1,
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     result,
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch2,
1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch3,
1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     gc_required,
1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     TAG_OBJECT);
1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map, length and hash field.
1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->ascii_string_map()));
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, length);
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SmiTag(scratch1);
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, String::kHashFieldOffset),
1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Immediate(String::kEmptyHashField));
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13939ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickvoid MacroAssembler::AllocateAsciiString(Register result,
13949ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                         int length,
13959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                         Register scratch1,
13969ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                         Register scratch2,
13979ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                         Label* gc_required) {
13989ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  ASSERT(length > 0);
13999ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate ASCII string in new space.
14019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  AllocateInNewSpace(SeqAsciiString::SizeFor(length),
14029ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                     result,
14039ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                     scratch1,
14049ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                     scratch2,
14059ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                     gc_required,
14069ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                     TAG_OBJECT);
14079ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
14089ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Set the map, length and hash field.
14099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, HeapObject::kMapOffset),
141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->ascii_string_map()));
14119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kLengthOffset),
14129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(Smi::FromInt(length)));
14139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(FieldOperand(result, String::kHashFieldOffset),
14149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Immediate(String::kEmptyHashField));
14159ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
14169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
14179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
1418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch1,
1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Register scratch2,
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                        Label* gc_required) {
1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate heap number in new space.
1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AllocateInNewSpace(ConsString::kSize,
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     result,
1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch1,
1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch2,
1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     gc_required,
1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     TAG_OBJECT);
1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->cons_string_map()));
1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::AllocateAsciiConsString(Register result,
1437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             Register scratch1,
1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             Register scratch2,
1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             Label* gc_required) {
1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate heap number in new space.
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AllocateInNewSpace(ConsString::kSize,
1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     result,
1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch1,
1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     scratch2,
1445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     gc_required,
1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     TAG_OBJECT);
1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the map. The other fields are left uninitialized.
1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(FieldOperand(result, HeapObject::kMapOffset),
145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->cons_ascii_string_map()));
1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
145569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch1,
145669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Register scratch2,
145769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                          Label* gc_required) {
145869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
145969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  AllocateInNewSpace(SlicedString::kSize,
146069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     result,
146169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     scratch1,
146269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     scratch2,
146369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     gc_required,
146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     TAG_OBJECT);
146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
146669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
146769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
146869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Immediate(isolate()->factory()->sliced_string_map()));
146969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
147069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
147169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid MacroAssembler::AllocateAsciiSlicedString(Register result,
147369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               Register scratch1,
147469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               Register scratch2,
147569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               Label* gc_required) {
147669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate heap number in new space.
147769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  AllocateInNewSpace(SlicedString::kSize,
147869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     result,
147969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     scratch1,
148069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     scratch2,
148169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     gc_required,
148269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                     TAG_OBJECT);
148369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
148469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Set the map. The other fields are left uninitialized.
148569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  mov(FieldOperand(result, HeapObject::kMapOffset),
148669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Immediate(isolate()->factory()->sliced_ascii_string_map()));
148769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
148869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
148969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copy memory, byte-by-byte, from source to destination.  Not optimized for
1491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// long or aligned copies.  The contents of scratch and length are destroyed.
1492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Source and destination are incremented by length.
1493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Many variants of movsb, loop unrolling, word moves, and indexed operands
1494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// have been tried here already, and this is fastest.
1495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A simpler loop is faster on small copies, but 30% slower on large ones.
1496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// The cld() instruction must have been emitted, to set the direction flag(),
1497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// before calling this function.
1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::CopyBytes(Register source,
1499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register destination,
1500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register length,
1501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               Register scratch) {
1502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label loop, done, short_string, short_loop;
1503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Experimentation shows that the short string loop is faster if length < 10.
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(length, Immediate(10));
1505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  j(less_equal, &short_string);
1506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(source.is(esi));
1508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(destination.is(edi));
1509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(length.is(ecx));
1510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Because source is 4-byte aligned in our uses of this function,
1512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // we keep source aligned for the rep_movs call by copying the odd bytes
1513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // at the end of the ranges.
1514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, Operand(source, length, times_1, -4));
1515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(Operand(destination, length, times_1, -4), scratch);
1516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov(scratch, ecx);
1517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  shr(ecx, 2);
1518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  rep_movs();
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch, Immediate(0x3));
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(destination, scratch);
1521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  jmp(&done);
1522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_string);
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(length, length);
1525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  j(zero, &done);
1526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&short_loop);
1528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(scratch, Operand(source, 0));
1529b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mov_b(Operand(destination, 0), scratch);
1530b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(source);
1531b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  inc(destination);
1532b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  dec(length);
1533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  j(not_zero, &short_loop);
1534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bind(&done);
15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register end_offset,
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&entry);
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(Operand(start_offset, 0), filler);
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(start_offset, Immediate(kPointerSize));
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(start_offset, end_offset);
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(less, &loop);
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::BooleanBitTest(Register object,
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int field_offset,
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int bit_index) {
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bit_index += kSmiTagSize + kSmiShiftSize;
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsPowerOf2(kBitsPerByte));
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_index = bit_index / kBitsPerByte;
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_bit_index = bit_index & (kBitsPerByte - 1);
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(FieldOperand(object, field_offset + byte_index),
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         static_cast<byte>(1 << byte_bit_index));
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok);
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(op, op);
1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(sign, then_label);
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op1,
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op2,
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(result, result);
1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok);
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, op1);
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(scratch, op2);
1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(sign, then_label);
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss,
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             bool miss_on_bound_function) {
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
15993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(function, miss);
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(function, JS_FUNCTION_TYPE, result);
1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, miss);
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (miss_on_bound_function) {
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If a bound function, go to miss label.
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch,
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BooleanBitTest(scratch, SharedFunctionInfo::kCompilerHintsOffset,
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   SharedFunctionInfo::kBoundFunction);
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(not_zero, miss);
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_instance;
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &non_instance);
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result,
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(result, Immediate(isolate()->factory()->the_hole_value()));
1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, miss);
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, scratch);
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, &done);
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result, FieldOperand(result, Map::kPrototypeOffset));
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(&done);
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(result, FieldOperand(result, Map::kConstructorOffset));
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) {
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::TailCallStub(CodeStub* stub) {
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
166185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
166285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(argc >= 1 && generating_stub());
166385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
1664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
1665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 0) {
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(eax, Immediate(isolate()->factory()->undefined_value()));
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the low kHashShift bits.
168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  and_(hash, String::kArrayIndexValueMask);
169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STATIC_ASSERT(String::kHashShift >= kSmiTagSize && kSmiTag == 0);
169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (String::kHashShift > kSmiTagSize) {
169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    shr(hash, String::kHashShift - kSmiTagSize);
169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!index.is(hash)) {
169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    mov(index, hash);
169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(id), num_arguments);
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
170644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForId(id);
1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Set(eax, Immediate(function->nargs));
170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(function, isolate())));
17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CEntryStub ces(1, kSaveFPRegs);
1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallStub(&ces);
1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
171444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 int num_arguments) {
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
17254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
17264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
17274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
17284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Set(eax, Immediate(num_arguments));
172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ebx, Immediate(ExternalReference(f, isolate())));
17304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub ces(1);
17314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CallExternalReference(ExternalReference ref,
1736bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                           int num_arguments) {
1737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(eax, Immediate(num_arguments));
1738bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  mov(ebx, Immediate(ref));
1739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CEntryStub stub(1);
1741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CallStub(&stub);
1742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
1743bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1744bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Set(eax, Immediate(num_arguments));
17536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext);
17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TailCallExternalReference(ExternalReference(fid, isolate()),
176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            num_arguments,
176244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            result_size);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// If true, a Handle<T> returned by value from a function with cdecl calling
1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// convention will be returned directly as a value of location_ field in a
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// register eax.
1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// If false, it is returned as a pointer to a preallocated by caller memory
1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// region. Pointer to this region should be passed to a function as an
1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// implicit first argument.
1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__)
1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const bool kReturnHandlesDirectly = true;
17745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#else
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const bool kReturnHandlesDirectly = false;
17765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif
17775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
17785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
17795913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckOperand ApiParameterOperand(int index) {
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Operand(
1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize);
1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
17853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::PrepareCallApiFunction(int argc) {
1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (kReturnHandlesDirectly) {
17878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    EnterApiExitFrame(argc);
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // When handles are returned directly we don't have to allocate extra
17895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    // space for and pass an out parameter.
17903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (emit_debug_code()) {
17913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(esi, Immediate(BitCast<int32_t>(kZapValue)));
17923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
17945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    // We allocate two additional slots: return value and pointer to it.
17958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    EnterApiExitFrame(argc + 2);
1796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
17975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    // The argument slots are filled as follows:
17985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    //
17993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    //   n + 1: output slot
18005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    //   n: arg n
18015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    //   ...
18025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    //   1: arg1
18033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    //   0: pointer to the output slot
18048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    lea(esi, Operand(esp, (argc + 1) * kPointerSize));
18063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(Operand(esp, 0 * kPointerSize), esi);
180744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
18083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(Operand(esi, 0), Immediate(0));
18098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
18105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
18118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
18128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CallApiFunctionAndReturn(Address function_address,
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int stack_space) {
18165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference next_address =
18175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_next_address();
18185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference limit_address =
18195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_limit_address();
18205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference level_address =
18215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      ExternalReference::handle_scope_level_address();
1822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Allocate HandleScope in callee-save registers.
18245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(ebx, Operand::StaticVariable(next_address));
18255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(edi, Operand::StaticVariable(limit_address));
18265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  add(Operand::StaticVariable(level_address), Immediate(1));
18275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call the api function.
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function_address, RelocInfo::RUNTIME_ENTRY);
1830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!kReturnHandlesDirectly) {
18323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // PrepareCallApiFunction saved pointer to the output slot into
18333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // callee-save register esi.
18343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(eax, Operand(esi, 0));
18355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label empty_handle;
18385913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label prologue;
18395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label promote_scheduled_exception;
18405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label delete_allocated_handles;
18415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Label leave_exit_frame;
18425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
18435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the result handle holds 0.
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(eax, eax);
1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &empty_handle);
18465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was non-zero.  Dereference to get the result value.
18475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(eax, Operand(eax, 0));
18485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&prologue);
18495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // No more valid handles (the result handle was the last one). Restore
18505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // previous handle scope.
18515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(Operand::StaticVariable(next_address), ebx);
18525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  sub(Operand::StaticVariable(level_address), Immediate(1));
18535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Assert(above_equal, "Invalid HandleScope level");
18545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  cmp(edi, Operand::StaticVariable(limit_address));
1855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &delete_allocated_handles);
18565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&leave_exit_frame);
18575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
18585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Check if the function scheduled an exception.
18595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  ExternalReference scheduled_exception_address =
186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::scheduled_exception_address(isolate());
18615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  cmp(Operand::StaticVariable(scheduled_exception_address),
186244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Immediate(isolate()->factory()->the_hole_value()));
1863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &promote_scheduled_exception);
18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LeaveApiExitFrame();
18658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ret(stack_space * kPointerSize);
18665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&promote_scheduled_exception);
18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&empty_handle);
18705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // It was zero; the result is undefined.
187144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(eax, isolate()->factory()->undefined_value());
18725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&prologue);
18735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
18745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // HandleScope limit has changed. Delete allocated extensions.
187544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference delete_extensions =
187644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::delete_handle_scope_extensions(isolate());
18775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  bind(&delete_allocated_handles);
18785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(Operand::StaticVariable(limit_address), edi);
18795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(edi, eax);
188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address()));
188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(eax, Immediate(delete_extensions));
18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(eax);
18835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  mov(eax, edi);
18845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  jmp(&leave_exit_frame);
1885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, Immediate(ext));
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub ces(1);
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This macro takes the dst register to make the code more readable
1898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // at the call sites. However, the dst register has to be ecx to
1899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // follow the calling convention which requires the call type to be
1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in ecx.
1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(dst.is(ecx));
1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (call_kind == CALL_AS_FUNCTION) {
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Set to some non-zero smi by updating the least significant
1904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // byte.
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov_b(dst, 1 << kSmiTagSize);
1906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Set to smi zero by clearing the register.
19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    xor_(dst, dst);
1909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Handle<Code> code_constant,
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const Operand& code_operand,
1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance done_near,
1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(actual.is_immediate());
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(eax, actual.immediate());
1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(ebx, expected.immediate());
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), actual.immediate());
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(ebx));
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(eax, actual.immediate());
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cmp(expected.reg(), actual.reg());
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(actual.reg().is(eax));
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(ebx));
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!code_constant.is_null()) {
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(edx, Immediate(code_constant));
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!code_operand.is_reg(edx)) {
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(edx, code_operand);
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(ecx, call_kind);
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      call(adaptor, RelocInfo::CODE_TARGET);
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, done_near);
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(ecx, call_kind);
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(adaptor, RelocInfo::CODE_TARGET);
1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(const Operand& code,
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                InvokeFlag flag,
1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InvokePrologue(expected, actual, Handle<Code>::null(), code,
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &done, &definitely_mismatches, flag, Label::kNear,
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 call_wrapper, call_kind);
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(ecx, call_kind);
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(flag == JUMP_FUNCTION);
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(ecx, call_kind);
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                InvokeFlag flag,
2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand dummy(eax, 0);
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokePrologue(expected, actual, code, dummy, &done, &definitely_mismatches,
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 flag, Label::kNear, call_wrapper, call_kind);
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code, rmode));
20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(ecx, call_kind);
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code, rmode);
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(flag == JUMP_FUNCTION);
20433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetCallKind(ecx, call_kind);
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code, rmode);
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(fun.is(edi));
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
20637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SmiUntag(ebx);
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(ebx);
2066791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             expected, actual, flag, call_wrapper, call_kind);
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    InvokeFlag flag,
2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2079402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadHeapObject(edi, function);
2081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2083402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(function->shared()->formal_parameter_count());
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             expected, actual, flag, call_wrapper, call_kind);
2089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2090402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   InvokeFlag flag,
2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a builtin without a valid frame.
20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(flag == JUMP_FUNCTION || has_frame());
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Rely on the assertion to check that the number of provided
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments match the expected number of arguments. Fake a
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parameter count to avoid emitting code to do the check.
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(0);
2102791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(edi, id);
2103791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             expected, expected, flag, call_wrapper, CALL_AS_METHOD);
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2108791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
2109791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                        Builtins::JavaScript id) {
2110791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Load the JavaScript builtin function from the builtins object.
21116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
21126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
2113791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  mov(target, FieldOperand(target,
2114791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
2115791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2118791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
2119791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!target.is(edi));
2120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Load the JavaScript builtin function from the builtins object.
2121791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(edi, id);
2122791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Load the code entry point from the function into the target register.
2123791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
21303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
21323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
21341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
21351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Slot is in the current function context.  Move it into the
21361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // destination register in case we store into it (the write barrier
21371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // cannot be allowed to destroy the context in esi).
21381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(dst, esi);
21391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
21401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
21413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context chain
21421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e., the static scope chain and runtime context chain do not agree).
21431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A variable occurring in such a scope should have slot type LOOKUP and
21441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // not CONTEXT.
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
21463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(dst, HeapObject::kMapOffset),
21473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->factory()->with_context_map());
21483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Check(not_equal, "Variable resolved to with context.");
2149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
21553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the global or builtins object from the current context.
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_index =
21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(expected_kind);
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(map_in_out, Operand(scratch, Context::SlotOffset(expected_index)));
21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
21683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int trans_index =
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Context::GetContextMapIndexFromElementsKind(transitioned_kind);
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(map_in_out, Operand(scratch, Context::SlotOffset(trans_index)));
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadInitialArrayMap(
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register function_in, Register scratch, Register map_out) {
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!function_in.is(map_out));
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(map_out, FieldOperand(function_in,
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            JSFunction::kPrototypeOrInitialMapOffset));
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_smi_only_arrays) {
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FAST_ELEMENTS,
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        map_out,
21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch,
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        &done);
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
219380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
219480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the global or builtins object from the current context.
219580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
219680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the global context from the global or builtins object.
219780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset));
219880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the function from the global context.
219980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(function, Operand(function, Context::SlotOffset(index)));
220080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
220180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
220280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
220380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
220480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Register map) {
220580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map.  The global functions all have initial maps.
220680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
220744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
220880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label ok, fail;
2209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
221080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    jmp(&ok);
221180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&fail);
221280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Abort("Global functions must have initial map");
221380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    bind(&ok);
221480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
221580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
221680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Store the value in register src in the safepoint register stack
2219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// slot for register dst.
2220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(SafepointRegisterSlot(dst), src);
2227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(dst, SafepointRegisterSlot(src));
2232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the lowest encoding,
2242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are furthest away from
2243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack pointer.
2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return kNumSafepointRegisters - reg_code - 1;
2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadHeapObject(Register result,
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Handle<HeapObject> object) {
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(object);
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(result, Operand::Cell(cell));
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(result, object);
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(object);
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(Operand::Cell(cell));
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Push(object);
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
22781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
22791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
22801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
22811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    pop(scratch);
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(bytes_dropped));
22831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    push(scratch);
22841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
22851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
22861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
22871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
2290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(stack_elements * kPointerSize));
2292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
22960d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
22970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
22980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    mov(dst, src);
22990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
23000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
23010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
23020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inc(operand);
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(operand, Immediate(value));
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      dec(operand);
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(operand, Immediate(value));
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::IncrementCounter(Condition cc,
2337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(value > 0);
2340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2342d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2343d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2344d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    IncrementCounter(counter, value);
2345d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2346d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::DecrementCounter(Condition cc,
2352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      StatsCounter* counter,
2353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                      int value) {
2354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(value > 0);
2355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_native_code_counters && counter->Enabled()) {
2356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label skip;
2357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    j(NegateCondition(cc), &skip);
2358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pushfd();
2359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DecrementCounter(counter, value);
2360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    popfd();
2361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bind(&skip);
2362d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2363d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2364d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) {
236744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) Check(cc, msg);
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
237244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate()->factory();
2374756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2375756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
237644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_array_map()));
2377756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2378756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(FieldOperand(elements, HeapObject::kMapOffset),
23793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Immediate(factory->fixed_double_array_map()));
23803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok);
23813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmp(FieldOperand(elements, HeapObject::kMapOffset),
238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Immediate(factory->fixed_cow_array_map()));
2383756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
2384756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Abort("JSObject with fast elements map has slow elements");
2385756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2386756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2389756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) {
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L);
2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Abort(msg);
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
24006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment = OS::ActivationFrameAlignment();
24016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
24026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
24036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(IsPowerOf2(frame_alignment));
24046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
24056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    test(esp, Immediate(frame_alignment_mask));
24066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
24076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
24086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
24096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
24106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
24116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) {
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We want to pass the msg string like a smi to avoid GC
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // problems, however msg is not guaranteed to be aligned
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properly. Instead, we pass an aligned pointer that is
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a proper v8 smi, but also pass the alignment difference
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the real pointer as a smi.
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(eax);
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(p0));
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0))));
24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Disable stub call restrictions to always allow calls to abort.
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime(Runtime::kAbort, 2);
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(descriptors,
2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FieldOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(descriptors, &not_smi);
2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(descriptors, isolate()->factory()->empty_descriptor_array());
2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&not_smi);
2455756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2456756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2457756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
24580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::LoadPowerOf2(XMMRegister dst,
24590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  Register scratch,
24600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                  int power) {
24610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(is_uintn(power + HeapNumber::kExponentBias,
24620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  HeapNumber::kExponentBits));
24630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  mov(scratch, Immediate(power + HeapNumber::kExponentBias));
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movd(dst, scratch);
24650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  psllq(dst, HeapNumber::kMantissaBits);
24660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
24670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
24680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
2470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register instance_type,
2471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register scratch,
24726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* failure) {
2473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (!scratch.is(instance_type)) {
2474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    mov(scratch, instance_type);
2475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
2476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  and_(scratch,
2477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  cmp(scratch, kStringTag | kSeqStringTag | kAsciiStringTag);
2479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(not_equal, failure);
2480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2481402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
2484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register object2,
2485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register scratch1,
2486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register scratch2,
2487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Label* failure) {
2488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that both objects are not smis.
248969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(scratch1, object1);
24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(scratch1, object2);
24923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpIfSmi(scratch1, failure);
2493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load instance type for both strings.
2495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that both are flat ASCII strings.
2501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kFlatAsciiStringMask =
2502d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2503d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Interleave bits from both instance types and compare them in one check.
2505d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  and_(scratch1, kFlatAsciiStringMask);
2507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  and_(scratch2, kFlatAsciiStringMask);
2508d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2509d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3));
2510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(not_equal, failure);
2511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
25146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
25158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int frame_alignment = OS::ActivationFrameAlignment();
25168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (frame_alignment != 0) {
25176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments words
25186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of esp.
25196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, esp);
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
25218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(IsPowerOf2(frame_alignment));
25228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    and_(esp, -frame_alignment);
25236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(Operand(esp, num_arguments * kPointerSize), scratch);
25246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sub(esp, Immediate(num_arguments * kPointerSize));
25266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
25276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
25316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
25326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Trashing eax is ok as it will be the return value.
25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(eax, Immediate(function));
25346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallCFunction(eax, num_arguments);
25356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(Register function,
25396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   int num_arguments) {
25403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(has_frame());
25416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
254244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
25436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
25446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
25456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  call(function);
25476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (OS::ActivationFrameAlignment() != 0) {
25486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(esp, Operand(esp, num_arguments * kPointerSize));
25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(esp, Immediate(num_arguments * kPointerSize));
25516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
25526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4) {
25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r2)) return true;
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r3)) return true;
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r1.is(r4)) return true;
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r3)) return true;
25603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r2.is(r4)) return true;
25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r3.is(r4)) return true;
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size)
25678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
25688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
25698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      masm_(Isolate::Current(), address, size + Assembler::kGap) {
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(cc == zero || cc == not_zero);
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, Immediate(~Page::kPageAlignmentMask));
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(scratch, Immediate(~Page::kPageAlignmentMask));
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    and_(scratch, object);
26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           static_cast<uint8_t>(mask));
26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
26123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch0,
26133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register scratch1,
26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_near) {
26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HasColor(object, scratch0, scratch1,
26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           on_black, on_black_near,
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           1, 0);  // kBlackBitPattern.
26193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::HasColor(Register object,
26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register bitmap_scratch,
26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register mask_scratch,
26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label* has_color,
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Label::Distance has_color_distance,
26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int first_bit,
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int second_bit) {
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label other_color, word_boundary;
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &word_boundary, Label::kNear);
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&other_color, Label::kNear);
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&word_boundary);
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1);
26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&other_color);
26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_reg, addr_reg);
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, shift);
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx,
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(bitmap_reg, ecx);
26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, addr_reg);
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(ecx, kPointerSizeLog2);
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(mask_reg, Immediate(1));
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shl_cl(mask_reg);
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::EnsureNotWhite(
26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register bitmap_scratch,
26763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register mask_scratch,
26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* value_is_white_and_not_data,
26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance distance) {
26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, &done, Label::kNear);
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for impossible bit pattern.
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    push(mask_scratch);
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // shl.  May overflow making the check conservative.
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    add(mask_scratch, mask_scratch);
27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pop(mask_scratch);
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is white.  We check whether it is data that doesn't need scanning.
27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Currently only checks for HeapNumber and non-cons strings.
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ecx;  // Holds map while checking type.
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = ecx;  // Holds length of object after checking type.
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_heap_number;
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_data_object;
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for heap-number
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(map, FieldOperand(value, HeapObject::kMapOffset));
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(map, FACTORY->heap_number_map());
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &not_heap_number, Label::kNear);
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(length, Immediate(HeapNumber::kSize));
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&is_data_object, Label::kNear);
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_heap_number);
27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for strings.
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's a string and it's not a cons string then it's an object containing
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no GC pointers.
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register instance_type = ecx;
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
27303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask);
27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_zero, value_is_white_and_not_data);
27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's a non-indirect (non-cons and non-slice) string.
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If it's external, the length is just ExternalString::kSize.
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_external;
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // External strings are the only ones with the kExternalStringTag bit
27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set.
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  test_b(instance_type, kExternalStringTag);
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(zero, &not_external, Label::kNear);
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(length, Immediate(ExternalString::kSize));
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&is_data_object, Label::kNear);
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&not_external);
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sequential string, either ASCII or UC16.
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kAsciiStringTag == 0x04);
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(length, Immediate(kStringEncodingMask));
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  xor_(length, Immediate(kStringEncodingMask));
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(length, Immediate(0x04));
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // by 2. If we multiply the string length as smi by this, it still
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // won't overflow a 32-bit value.
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(SeqAsciiString::kMaxSize, SeqTwoByteString::kMaxSize);
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(SeqAsciiString::kMaxSize <=
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  imul(length, FieldOperand(value, String::kLengthOffset));
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shr(length, 2 + kSmiTagSize + kSmiShiftSize);
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(length, Immediate(~kObjectAlignmentMask));
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&is_data_object);
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a data object, and it is white.  Mark it black.  Since we know
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that the object is white we can make it black by flipping one bit.
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      length);
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Check(less_equal, "Live Bytes Count overflow chunk size");
27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&done);
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label next;
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, eax);
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there are no elements.  Register ecx contains the
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // current JS object we've reached through the prototype chain.
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(FieldOperand(ecx, JSObject::kElementsOffset),
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->empty_fixed_array());
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that instance descriptors are not empty so that we can
27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // check for an enum cache.  Leave the map in ebx for the subsequent
27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // prototype load.
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
27953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBitField3Offset));
27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(edx, call_runtime);
27973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that there is an enum cache in the non-empty instance
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // descriptors (edx).  This is the case if the next enumeration
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // index field does not contain a smi.
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(edx, call_runtime);
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For all objects but the receiver, check that the cache is empty.
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_prototype;
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, eax);
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, &check_prototype, Label::kNear);
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(edx, isolate()->factory()->empty_fixed_array());
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the prototype from the map and loop if non-null.
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&check_prototype);
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmp(ecx, isolate()->factory()->null_value());
28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
2822