1864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
3864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// found in the LICENSE file.
4864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if V8_TARGET_ARCH_X87
8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
99aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org#include "src/base/bits.h"
1042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org#include "src/base/division-by-constant.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/bootstrapper.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/cpu-profiler.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/isolate-inl.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/runtime.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h"
18864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 {
20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal {
21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
22864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// -------------------------------------------------------------------------
23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// MacroAssembler implementation.
24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
25864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    : Assembler(arg_isolate, buffer, size),
27864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      generating_stub_(false),
28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      has_frame_(false) {
29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate() != NULL) {
30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // TODO(titzer): should we just use a null handle here instead?
31864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
32864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  isolate());
33864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
34864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
35864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
36864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
37864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
38e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!r.IsDouble());
39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (r.IsInteger8()) {
40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    movsx_b(dst, src);
41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsUInteger8()) {
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    movzx_b(dst, src);
43864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsInteger16()) {
44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    movsx_w(dst, src);
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsUInteger16()) {
46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    movzx_w(dst, src);
47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, src);
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
51864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
52864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
54e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!r.IsDouble());
55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (r.IsInteger8() || r.IsUInteger8()) {
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov_b(dst, src);
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsInteger16() || r.IsUInteger16()) {
58864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov_w(dst, src);
59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
60e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    if (r.IsHeapObject()) {
61e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      AssertNotSmi(src);
62e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    } else if (r.IsSmi()) {
63e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      AssertSmi(src);
64e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    }
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, src);
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
69864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(destination, value);
74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
76864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference roots_array_start =
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::roots_array_start(isolate());
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(destination, Immediate(index));
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(destination, Operand::StaticArray(destination,
80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        times_pointer_size,
81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        roots_array_start));
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
83864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StoreRoot(Register source,
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register scratch,
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Heap::RootListIndex index) {
88e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
89864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference roots_array_start =
90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::roots_array_start(isolate());
91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Immediate(index));
92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
93864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      source);
94864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
95864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CompareRoot(Register with,
98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register scratch,
99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Heap::RootListIndex index) {
100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference roots_array_start =
101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::roots_array_start(isolate());
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Immediate(index));
103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(with, Operand::StaticArray(scratch,
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                times_pointer_size,
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                roots_array_start));
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
110e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(with, value);
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CompareRoot(const Operand& with,
117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Heap::RootListIndex index) {
118e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index));
119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(with, value);
121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InNewSpace(
125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object,
126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch,
127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Condition cc,
128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* condition_met,
129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label::Distance condition_met_distance) {
130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cc == equal || cc == not_equal);
131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (scratch.is(object)) {
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(scratch, Immediate(~Page::kPageAlignmentMask));
133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, Immediate(~Page::kPageAlignmentMask));
135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(scratch, object);
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that we can use a test_b.
138e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(MemoryChunk::IN_FROM_SPACE < 8);
139e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(MemoryChunk::IN_TO_SPACE < 8);
140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int mask = (1 << MemoryChunk::IN_FROM_SPACE)
141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           | (1 << MemoryChunk::IN_TO_SPACE);
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If non-zero, the page belongs to new-space.
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         static_cast<uint8_t>(mask));
145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(cc, condition_met, condition_met_distance);
146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::RememberedSetHelper(
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object,  // Only used for debug checks.
15106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register addr, Register scratch, SaveFPRegsMode save_fp,
152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    MacroAssembler::RememberedSetFinalAction and_then) {
153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load store buffer top.
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference store_buffer =
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::store_buffer_top(isolate());
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand::StaticVariable(store_buffer));
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store pointer to buffer.
165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(scratch, 0), addr);
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Increment buffer top.
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(scratch, Immediate(kPointerSize));
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Write back new top of buffer.
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(store_buffer), scratch);
170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call stub on end of buffer.
171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for end of buffer.
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (and_then == kReturnAtEnd) {
174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label buffer_overflowed;
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(not_equal, &buffer_overflowed, Label::kNear);
176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ret(0);
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&buffer_overflowed);
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
179e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(and_then == kFallThroughAtEnd);
180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &done, Label::kNear);
181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
18206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStub(&store_buffer_overflow);
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (and_then == kReturnAtEnd) {
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ret(0);
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
187e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(and_then == kFallThroughAtEnd);
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&done);
189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
19306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::ClampTOSToUint8(Register result_reg) {
19406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label done, conv_failure;
19506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  sub(esp, Immediate(kPointerSize));
19606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnclex();
19706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fist_s(Operand(esp, 0));
19806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  pop(result_reg);
19906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87CheckIA();
20006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  j(equal, &conv_failure, Label::kNear);
20106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  test(result_reg, Immediate(0xFFFFFF00));
20206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  j(zero, &done, Label::kNear);
20306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  setcc(sign, result_reg);
20406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  sub(result_reg, Immediate(1));
20506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  and_(result_reg, Immediate(255));
20606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  jmp(&done, Label::kNear);
20706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  bind(&conv_failure);
20806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnclex();
20906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fldz();
21006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fld(1);
21106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  FCmp();
21206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  setcc(below, result_reg);  // 1 if negative, 0 if positive.
21306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  dec_b(result_reg);         // 0 if negative, 255 if positive.
21406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  bind(&done);
21506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
21606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
21706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::ClampUint8(Register reg) {
219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(reg, Immediate(0xFFFFFF00));
221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &done, Label::kNear);
222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  setcc(negative, reg);  // 1 if negative, 0 if positive.
223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  dec_b(reg);  // 0 if negative, 255 if positive.
224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::SlowTruncateToI(Register result_reg,
229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     Register input_reg,
230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     int offset) {
231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(stub.GetCode(), RelocInfo::CODE_TARGET);
233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TruncateX87TOSToI(Register result_reg) {
237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sub(esp, Immediate(kDoubleSize));
238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fst_d(MemOperand(esp, 0));
239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SlowTruncateToI(result_reg, esp, 0);
240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(esp, Immediate(kDoubleSize));
241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::X87TOSToI(Register result_reg,
245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               MinusZeroMode minus_zero_mode,
246b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                               Label* lost_precision, Label* is_nan,
247b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                               Label* minus_zero, Label::Distance dst) {
248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sub(esp, Immediate(kPointerSize));
250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld(0);
251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fist_s(MemOperand(esp, 0));
252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fild_s(MemOperand(esp, 0));
253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(result_reg);
254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  FCmp();
255b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  j(not_equal, lost_precision, dst);
256b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  j(parity_even, is_nan, dst);
257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result_reg, Operand(result_reg));
259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(not_zero, &done, Label::kNear);
260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // To check for minus zero, we load the value again as float, and check
261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // if that is still 0.
262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    sub(esp, Immediate(kPointerSize));
263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    fst_s(MemOperand(esp, 0));
264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pop(result_reg);
265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result_reg, Operand(result_reg));
266b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    j(not_zero, minus_zero, dst);
267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register input_reg) {
274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, slow_case;
275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SlowTruncateToI(result_reg, input_reg);
277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadUint32NoSSE2(Register src) {
282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(src);
284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fild_s(Operand(esp, 0));
285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(src, Immediate(0));
286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_sign, &done, Label::kNear);
287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference uint32_bias =
288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference::address_of_uint32_bias();
289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld_d(Operand::StaticVariable(uint32_bias));
290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  faddp(1);
291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(esp, Immediate(kPointerSize));
293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
29638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.orgvoid MacroAssembler::RecordWriteArray(
29706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register object, Register value, Register index, SaveFPRegsMode save_fp,
29806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    RememberedSetAction remembered_set_action, SmiCheck smi_check,
29938de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    PointersToHereCheck pointers_to_here_check_for_value) {
300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // First, check if a write barrier is even needed. The tests below
301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // catch stores of Smis.
302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Skip barrier if writing a smi.
305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (smi_check == INLINE_SMI_CHECK) {
306e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(0, kSmiTag);
307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(value, Immediate(kSmiTagMask));
308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &done);
309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Array access: calculate the destination address in the same manner as
312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // into an array of words.
314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dst = index;
315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(dst, Operand(object, index, times_half_pointer_size,
316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   FixedArray::kHeaderSize - kHeapObjectTag));
317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
31806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  RecordWrite(object, dst, value, save_fp, remembered_set_action,
31906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clobber clobbered input registers when running with the debug-code flag
324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // turned on to provoke errors.
325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
326e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
327e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(index, Immediate(bit_cast<int32_t>(kZapValue)));
328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::RecordWriteField(
33306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register object, int offset, Register value, Register dst,
33406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action,
33506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) {
336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // First, check if a write barrier is even needed. The tests below
337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // catch stores of Smis.
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Skip barrier if writing a smi.
341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (smi_check == INLINE_SMI_CHECK) {
342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfSmi(value, &done, Label::kNear);
343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Although the object register is tagged, the offset is relative to the start
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // of the object, so so offset must be a multiple of kPointerSize.
347e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsAligned(offset, kPointerSize));
348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(dst, FieldOperand(object, offset));
350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test_b(dst, (1 << kPointerSizeLog2) - 1);
353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &ok, Label::kNear);
354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
35806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  RecordWrite(object, dst, value, save_fp, remembered_set_action,
35906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clobber clobbered input registers when running with the debug-code flag
364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // turned on to provoke errors.
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
366e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
367e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(dst, Immediate(bit_cast<int32_t>(kZapValue)));
368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
37206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::RecordWriteForMap(Register object, Handle<Map> map,
37306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                       Register scratch1, Register scratch2,
37406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                       SaveFPRegsMode save_fp) {
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register address = scratch1;
378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value = scratch2;
379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    lea(address, FieldOperand(object, HeapObject::kMapOffset));
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test_b(address, (1 << kPointerSizeLog2) - 1);
383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &ok, Label::kNear);
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
388e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!object.is(value));
389e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!object.is(address));
390e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!value.is(address));
391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AssertNotSmi(object);
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!FLAG_incremental_marking) {
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
39738de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org  // Compute the address.
39838de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org  lea(address, FieldOperand(object, HeapObject::kMapOffset));
39938de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org
400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // A single check of the map's pages interesting flag suffices, since it is
401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // only set during incremental collection, and then it's also guaranteed that
402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the from object's page's interesting flag is also set.  This optimization
403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // relies on the fact that maps can never be in new space.
404e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!isolate()->heap()->InNewSpace(*map));
405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CheckPageFlagForMap(map,
406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      MemoryChunk::kPointersToHereAreInterestingMask,
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      zero,
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      &done,
409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      Label::kNear);
410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
41106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
41206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                       save_fp);
413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStub(&stub);
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
417dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  // Count number of write barriers in generated code.
418dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  isolate()->counters()->write_barriers_static()->Increment();
419dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
420dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clobber clobbered input registers when running with the debug-code flag
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // turned on to provoke errors.
423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
424e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
425e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(scratch1, Immediate(bit_cast<int32_t>(kZapValue)));
426e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(scratch2, Immediate(bit_cast<int32_t>(kZapValue)));
427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
43138de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.orgvoid MacroAssembler::RecordWrite(
43206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register object, Register address, Register value, SaveFPRegsMode fp_mode,
43306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    RememberedSetAction remembered_set_action, SmiCheck smi_check,
43438de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    PointersToHereCheck pointers_to_here_check_for_value) {
435e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!object.is(value));
436e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!object.is(address));
437e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!value.is(address));
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AssertNotSmi(object);
439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (remembered_set_action == OMIT_REMEMBERED_SET &&
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      !FLAG_incremental_marking) {
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(value, Operand(address, 0));
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &ok, Label::kNear);
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // First, check if a write barrier is even needed. The tests below
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // catch stores of Smis and stores into young gen.
455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (smi_check == INLINE_SMI_CHECK) {
458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Skip barrier if writing a smi.
459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfSmi(value, &done, Label::kNear);
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
46238de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
46338de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    CheckPageFlag(value,
46438de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                  value,  // Used as scratch.
46538de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                  MemoryChunk::kPointersToHereAreInterestingMask,
46638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                  zero,
46738de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                  &done,
46838de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                  Label::kNear);
46938de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org  }
470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CheckPageFlag(object,
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                value,  // Used as scratch.
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                MemoryChunk::kPointersFromHereAreInterestingMask,
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                zero,
474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                &done,
475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                Label::kNear);
476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
47706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
47806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                       fp_mode);
479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStub(&stub);
480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
483dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  // Count number of write barriers in generated code.
484dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  isolate()->counters()->write_barriers_static()->Increment();
485dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
486dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org
487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clobber clobbered registers when running with the debug-code flag
488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // turned on to provoke errors.
489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
490e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(address, Immediate(bit_cast<int32_t>(kZapValue)));
491e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::DebugBreak() {
497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Move(eax, Immediate(0));
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CEntryStub ces(isolate(), 1);
500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  static const int kMaxImmediateBits = 17;
506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!RelocInfo::IsNone(x.rmode_)) return false;
507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return !is_intn(x.x_, kMaxImmediateBits);
508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::SafeMove(Register dst, const Immediate& x) {
512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Move(dst, Immediate(x.x_ ^ jit_cookie()));
514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    xor_(dst, jit_cookie());
515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Move(dst, x);
517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::SafePush(const Immediate& x) {
522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(Immediate(x.x_ ^ jit_cookie()));
524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    xor_(Operand(esp, 0), Immediate(jit_cookie()));
525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(x);
527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CmpObjectType(Register heap_object,
532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   InstanceType type,
533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   Register map) {
534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CmpInstanceType(map, type);
536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       static_cast<int8_t>(type));
542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckFastElements(Register map,
546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       Label* fail,
547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       Label::Distance distance) {
548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_ELEMENTS == 2);
551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(FieldOperand(map, Map::kBitField2Offset),
553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Map::kMaximumBitField2FastHoleyElementValue);
554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, fail, distance);
555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckFastObjectElements(Register map,
559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Label* fail,
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Label::Distance distance) {
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_ELEMENTS == 2);
564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(FieldOperand(map, Map::kBitField2Offset),
566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Map::kMaximumBitField2FastHoleySmiElementValue);
567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below_equal, fail, distance);
568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(FieldOperand(map, Map::kBitField2Offset),
569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Map::kMaximumBitField2FastHoleyElementValue);
570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, fail, distance);
571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckFastSmiElements(Register map,
575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Label* fail,
576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Label::Distance distance) {
577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(FieldOperand(map, Map::kBitField2Offset),
580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Map::kMaximumBitField2FastHoleySmiElementValue);
581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, fail, distance);
582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StoreNumberToDoubleElements(
586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register maybe_number,
587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register elements,
588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register key,
589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch,
590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* fail,
591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int elements_offset) {
592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value;
593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CheckMap(maybe_number,
596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           isolate()->factory()->heap_number_map(),
597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           fail,
598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           DONT_DO_SMI_CHECK);
599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Double value, canonicalize NaN.
601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(FieldOperand(maybe_number, offset),
603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(kNaNOrInfinityLowerBoundUpper32));
604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(greater_equal, &maybe_nan, Label::kNear);
605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&not_nan);
607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference canonical_nan_reference =
608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_canonical_non_hole_nan();
609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset));
610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&have_double_value);
611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fstp_d(FieldOperand(elements, key, times_4,
612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      FixedDoubleArray::kHeaderSize - elements_offset));
613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&done);
614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&maybe_nan);
616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // it's an Infinity, and the non-NaN code path applies.
618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(greater, &is_nan, Label::kNear);
619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &not_nan);
621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&is_nan);
622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld_d(Operand::StaticVariable(canonical_nan_reference));
623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&have_double_value, Label::kNear);
624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&smi_value);
626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Value is a smi. Convert to a double and store.
627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Preserve original value.
628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, maybe_number);
629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiUntag(scratch);
630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(scratch);
631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fild_s(Operand(esp, 0));
632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(scratch);
633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fstp_d(FieldOperand(elements, key, times_4,
634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      FixedDoubleArray::kHeaderSize - elements_offset));
635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckMap(Register obj,
645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Handle<Map> map,
646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* fail,
647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              SmiCheckType smi_check_type) {
648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (smi_check_type == DO_SMI_CHECK) {
649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfSmi(obj, fail);
650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CompareMap(obj, map);
653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, fail);
654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::DispatchMap(Register obj,
658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register unused,
659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Handle<Map> map,
660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Handle<Code> success,
661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 SmiCheckType smi_check_type) {
662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label fail;
663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (smi_check_type == DO_SMI_CHECK) {
664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfSmi(obj, &fail);
665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, success);
668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&fail);
670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition MacroAssembler::IsObjectStringType(Register heap_object,
674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register map,
675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register instance_type) {
676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(instance_type, Immediate(kIsNotStringMask));
680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return zero;
681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition MacroAssembler::IsObjectNameType(Register heap_object,
685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register map,
686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register instance_type) {
687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(instance_type, static_cast<uint8_t>(LAST_NAME_TYPE));
690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return below_equal;
691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::IsObjectJSObjectType(Register heap_object,
695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Register map,
696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Register scratch,
697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Label* fail) {
698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  IsInstanceJSObjectType(map, scratch, fail);
700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::IsInstanceJSObjectType(Register map,
704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Register scratch,
705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Label* fail) {
706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch,
709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, fail);
711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::FCmp() {
715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fucompp();
716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(eax);
717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fnstsw_ax();
718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sahf();
719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(eax);
720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
72306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::FXamMinusZero() {
72406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fxam();
72506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  push(eax);
72606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnstsw_ax();
72706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  and_(eax, Immediate(0x4700));
72806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // For minus zero, C3 == 1 && C1 == 1.
72906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  cmp(eax, Immediate(0x4200));
73006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  pop(eax);
73106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fstp(0);
73206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
73306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
73406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
73506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::FXamSign() {
73606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fxam();
73706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  push(eax);
73806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnstsw_ax();
73906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // For negative value (including -0.0), C1 == 1.
74006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  and_(eax, Immediate(0x0200));
74106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  pop(eax);
74206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fstp(0);
74306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
74406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
74506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
74606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::X87CheckIA() {
74706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  push(eax);
74806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnstsw_ax();
74906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // For #IA, IE == 1 && SF == 0.
75006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  and_(eax, Immediate(0x0041));
75106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  cmp(eax, Immediate(0x0001));
75206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  pop(eax);
75306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
75406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
75506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
75606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org// rc=00B, round to nearest.
75706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org// rc=01B, round down.
75806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org// rc=10B, round up.
75906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org// rc=11B, round toward zero.
76006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::X87SetRC(int rc) {
76106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  sub(esp, Immediate(kPointerSize));
76206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fnstcw(MemOperand(esp, 0));
76306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  and_(MemOperand(esp, 0), Immediate(0xF3FF));
76406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  or_(MemOperand(esp, 0), Immediate(rc));
76506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  fldcw(MemOperand(esp, 0));
76606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  add(esp, Immediate(kPointerSize));
76706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
76806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
76906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
77079390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.comvoid MacroAssembler::X87SetFPUCW(int cw) {
77179390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  push(Immediate(cw));
77279390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  fldcw(MemOperand(esp, 0));
77379390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  add(esp, Immediate(kPointerSize));
77479390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com}
77579390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com
77679390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com
777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertNumber(Register object) {
778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    JumpIfSmi(object, &ok);
781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(object, HeapObject::kMapOffset),
782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->factory()->heap_number_map());
783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kOperandNotANumber);
784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertSmi(Register object) {
790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(object, Immediate(kSmiTagMask));
792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kOperandIsNotASmi);
793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertString(Register object) {
798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(object, Immediate(kSmiTagMask));
800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kOperandIsASmiAndNotAString);
801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(object);
802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(object, FieldOperand(object, HeapObject::kMapOffset));
803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pop(object);
805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(below, kOperandIsNotAString);
806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertName(Register object) {
811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(object, Immediate(kSmiTagMask));
813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kOperandIsASmiAndNotAName);
814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(object);
815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(object, FieldOperand(object, HeapObject::kMapOffset));
816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CmpInstanceType(object, LAST_NAME_TYPE);
817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pop(object);
818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(below_equal, kOperandIsNotAName);
819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done_checking;
826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AssertNotSmi(object);
827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(object, isolate()->factory()->undefined_value());
828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &done_checking);
829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(object, 0),
830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(isolate()->factory()->allocation_site_map()));
831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Assert(equal, kExpectedUndefinedOrCell);
832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&done_checking);
833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertNotSmi(Register object) {
838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(object, Immediate(kSmiTagMask));
840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kOperandIsASmi);
841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StubPrologue() {
846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(ebp);  // Caller's frame pointer.
847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebp, esp);
848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(esi);  // Callee's context.
849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(Smi::FromInt(StackFrame::STUB)));
850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Prologue(bool code_pre_aging) {
854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PredictableCodeSizeScope predictible_code_size_scope(this,
855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      kNoCodeAgeSequenceLength);
856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (code_pre_aging) {
857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Pre-age the code.
858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        RelocInfo::CODE_AGE_SEQUENCE);
860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(ebp);  // Caller's frame pointer.
863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(ebp, esp);
864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(esi);  // Callee's context.
865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(edi);  // Callee's JS function.
866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(ebp);
872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebp, esp);
873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(esi);
874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(Smi::FromInt(type)));
875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(CodeObject()));
876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kCodeObjectNotProperlyPatched);
879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(Smi::FromInt(type)));
887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kStackFrameTypesMustMatch);
888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  leave();
890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EnterExitFramePrologue() {
894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set up the frame structure on the stack.
895e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
896e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
897e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(ebp);
899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebp, esp);
900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Reserve room for entry stack pointer and push the code object.
902e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ExitFrameConstants::kSPOffset  == -1 * kPointerSize);
903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(0));  // Saved entry sp, patched before call.
904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save the frame pointer and the context in top.
907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference context_address(Isolate::kContextAddress, isolate());
909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(context_address), esi);
911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
91406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
91506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Optionally save FPU state.
91606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (save_doubles) {
91706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Store FPU state to m108byte.
91806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    int space = 108 + argc * kPointerSize;
91906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    sub(esp, Immediate(space));
92006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    const int offset = -2 * kPointerSize;  // entry fp + code object.
92106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    fnsave(MemOperand(ebp, offset - 108));
92206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else {
92306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    sub(esp, Immediate(argc * kPointerSize));
92406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the required frame alignment for the OS.
9275de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (kFrameAlignment > 0) {
9299aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(esp, -kFrameAlignment);
931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Patch the saved entry sp.
934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
93806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::EnterExitFrame(bool save_doubles) {
939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EnterExitFramePrologue();
940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set up argc and argv in callee-saved registers.
942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(edi, eax);
944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(esi, Operand(ebp, eax, times_4, offset));
945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Reserve space for argc, argv and isolate.
94706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  EnterExitFrameEpilogue(3, save_doubles);
948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EnterApiExitFrame(int argc) {
952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EnterExitFramePrologue();
95306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  EnterExitFrameEpilogue(argc, false);
954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
95706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::LeaveExitFrame(bool save_doubles) {
95806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Optionally restore FPU state.
95906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (save_doubles) {
96006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    const int offset = -2 * kPointerSize;
96106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    frstor(MemOperand(ebp, offset - 108));
96206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
96306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the return address from the stack and restore the frame pointer.
965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, Operand(ebp, 1 * kPointerSize));
966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebp, Operand(ebp, 0 * kPointerSize));
967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Pop the arguments and the receiver from the caller stack.
969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(esp, Operand(esi, 1 * kPointerSize));
970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the return address to get ready to return.
972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(ecx);
973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LeaveExitFrameEpilogue(true);
975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore current context from top and clear it in debug mode.
980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference context_address(Isolate::kContextAddress, isolate());
981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (restore_context) {
982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(esi, Operand::StaticVariable(context_address));
983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(context_address), Immediate(0));
986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clear the top frame.
989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       isolate());
991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esp, ebp);
997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(ebp);
998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LeaveExitFrameEpilogue(restore_context);
1000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::PushTryHandler(StackHandler::Kind kind,
1004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    int handler_index) {
1005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust this code if not the case.
1006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We will build up the handler from the bottom by pushing on the stack.
1014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // First push the frame pointer and context.
1015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (kind == StackHandler::JS_ENTRY) {
1016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The frame pointer does not point to a JS frame so we save NULL for
1017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // ebp. We expect the code throwing an exception to check ebp before
1018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // dereferencing it to restore the context.
1019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(Immediate(0));  // NULL frame pointer.
1020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(Immediate(Smi::FromInt(0)));  // No context.
1021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(ebp);
1023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(esi);
1024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the state and the code object.
1026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  unsigned state =
1027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      StackHandler::IndexField::encode(handler_index) |
1028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      StackHandler::KindField::encode(kind);
1029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(state));
1030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Push(CodeObject());
1031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Link the current handler as the next handler.
1033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Operand::StaticVariable(handler_address));
1035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set this new handler as the current one.
1036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(handler_address), esp);
1037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::PopTryHandler() {
1041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(Operand::StaticVariable(handler_address));
1044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
1045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::JumpToHandlerEntry() {
1049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compute the handler entry address and jump to it.  The handler table is
1050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // a fixed array of (smi-tagged) code offsets.
1051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax = exception, edi = code object, edx = state.
1052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset));
1053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(edx, StackHandler::kKindWidth);
1054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize));
1055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiUntag(edx);
1056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
1057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(edi);
1058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Throw(Register value) {
1062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust this code if not the case.
1063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The exception is expected in eax.
1071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!value.is(eax)) {
1072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(eax, value);
1073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Drop the stack pointer to the top of the top handler.
1075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esp, Operand::StaticVariable(handler_address));
1077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore the next handler.
1078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(Operand::StaticVariable(handler_address));
1079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Remove the code object and state, compute the handler address in edi.
1081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(edi);  // Code object.
1082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(edx);  // Index and state.
1083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore the context and frame pointer.
1085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(esi);  // Context.
1086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(ebp);  // Frame pointer.
1087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the handler is a JS frame, restore the context to the frame.
1089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
1090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ebp or esi.
1091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label skip;
1092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(esi, esi);
1093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &skip, Label::kNear);
1094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
1095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&skip);
1096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpToHandlerEntry();
1098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::ThrowUncatchable(Register value) {
1102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust this code if not the case.
1103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The exception is expected in eax.
1111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!value.is(eax)) {
1112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(eax, value);
1113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Drop the stack pointer to the top of the top stack handler.
1115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
1116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esp, Operand::StaticVariable(handler_address));
1117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Unwind the handlers until the top ENTRY handler is found.
1119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label fetch_next, check_kind;
1120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&check_kind, Label::kNear);
1121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&fetch_next);
1122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
1123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&check_kind);
1125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
1126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(Operand(esp, StackHandlerConstants::kStateOffset),
1127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Immediate(StackHandler::KindField::kMask));
1128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, &fetch_next);
1129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the top handler address to next handler past the top ENTRY handler.
1131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(Operand::StaticVariable(handler_address));
1132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Remove the code object and state, compute the handler address in edi.
1134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(edi);  // Code object.
1135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(edx);  // Index and state.
1136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clear the context pointer and frame pointer (0 was saved in the handler).
1138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(esi);
1139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(ebp);
1140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpToHandlerEntry();
1142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Register scratch1,
1147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Register scratch2,
1148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Label* miss) {
1149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label same_contexts;
1150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!holder_reg.is(scratch1));
1152e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!holder_reg.is(scratch2));
1153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch1.is(scratch2));
1154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load current lexical context from the stack frame.
1156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset));
1157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // When generating debug code, make sure the lexical context is set.
1159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
1160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(scratch1, Immediate(0));
1161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
1162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the native context of the current context.
1164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset =
1165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
1166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, FieldOperand(scratch1, offset));
1167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, FieldOperand(scratch1, GlobalObject::kNativeContextOffset));
1168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check the context is a native context.
1170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
1171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Read the first word and compare to native_context_map.
1172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
1173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->factory()->native_context_map());
1174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if both contexts are the same.
1178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &same_contexts);
1180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compare security tokens, save holder_reg on the stack so we can use it
1182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // as a temporary register.
1183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the security token in the calling global object is
1185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // compatible with the security token in the receiving global
1186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object.
1187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch2,
1188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check the context is a native context.
1191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
1192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(scratch2, isolate()->factory()->null_value());
1193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
1194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Read the first word and compare to native_context_map(),
1196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
1197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->factory()->native_context_map());
1198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
1199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int token_offset = Context::kHeaderSize +
1202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
1203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, FieldOperand(scratch1, token_offset));
1204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch1, FieldOperand(scratch2, token_offset));
1205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, miss);
1206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&same_contexts);
1208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Compute the hash code from the untagged key.  This must be kept in sync with
1212f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// code-stub-hydrogen.cc
1214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org//
1215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Note: r0 will contain hash code
1216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
1217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Xor original key with a seed.
1218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (serializer_enabled()) {
1219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ExternalReference roots_array_start =
1220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference::roots_array_start(isolate());
1221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, Immediate(Heap::kHashSeedRootIndex));
1222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch,
1223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
1224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SmiUntag(scratch);
1225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    xor_(r0, scratch);
1226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t seed = isolate()->heap()->HashSeed();
1228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    xor_(r0, Immediate(seed));
1229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = ~hash + (hash << 15);
1232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, r0);
1233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  not_(r0);
1234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shl(scratch, 15);
1235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(r0, scratch);
1236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = hash ^ (hash >> 12);
1237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, r0);
1238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(scratch, 12);
1239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  xor_(r0, scratch);
1240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = hash + (hash << 2);
1241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(r0, Operand(r0, r0, times_4, 0));
1242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = hash ^ (hash >> 4);
1243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, r0);
1244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(scratch, 4);
1245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  xor_(r0, scratch);
1246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = hash * 2057;
1247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  imul(r0, r0, 2057);
1248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hash = hash ^ (hash >> 16);
1249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, r0);
1250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(scratch, 16);
1251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  xor_(r0, scratch);
1252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
1257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register elements,
1258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register key,
1259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register r0,
1260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register r1,
1261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register r2,
1262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              Register result) {
1263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Register use:
1264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // elements - holds the slow-case elements of the receiver and is unchanged.
1266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // key      - holds the smi key on entry and is unchanged.
1268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Scratch registers:
1270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // r0 - holds the untagged key on entry and holds the hash once computed.
1272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // r1 - used to hold the capacity mask of the dictionary
1274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // r2 - used for the index into the dictionary.
1276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  //
1277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result - holds the result on exit if the load succeeds and we fall through.
1278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
1280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GetNumberHash(r0, r1);
1282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compute capacity mask.
1284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset));
1285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(r1, kSmiTagSize);  // convert smi to int
1286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  dec(r1);
1287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate an unrolled loop that performs a few probes before giving up.
1289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < kNumberDictionaryProbes; i++) {
1290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Use r2 for index calculations and keep the hash intact in r0.
1291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(r2, r0);
1292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
1293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (i > 0) {
1294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
1295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(r2, r1);
1297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Scale the index by multiplying by the entry size.
1299e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(SeededNumberDictionary::kEntrySize == 3);
1300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
1301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check if the key matches.
1303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(key, FieldOperand(elements,
1304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          r2,
1305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          times_pointer_size,
1306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          SeededNumberDictionary::kElementsStartOffset));
1307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (i != (kNumberDictionaryProbes - 1)) {
1308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(equal, &done);
1309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(not_equal, miss);
1311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
1315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the value is a normal propety.
1316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kDetailsOffset =
1317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
1318e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(NORMAL, 0);
1319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
1320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
1321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, miss);
1322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the value at the masked, scaled index.
1324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kValueOffset =
1325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
1326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
1327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadAllocationTopHelper(Register result,
1331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register scratch,
1332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             AllocationFlags flags) {
1333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference allocation_top =
1334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Just return if allocation top is already known.
1337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & RESULT_CONTAINS_TOP) != 0) {
1338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // No use of scratch if allocation top is provided.
1339e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(scratch.is(no_reg));
1340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
1341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Assert that result actually contains top on entry.
1342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(result, Operand::StaticVariable(allocation_top));
1343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(equal, kUnexpectedAllocationTop);
1344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
1345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Move address of new object to result. Use scratch register if available.
1349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (scratch.is(no_reg)) {
1350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(result, Operand::StaticVariable(allocation_top));
1351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, Immediate(allocation_top));
1353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(result, Operand(scratch, 0));
1354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               Register scratch,
1360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               AllocationFlags flags) {
1361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
1362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result_end, Immediate(kObjectAlignmentMask));
1363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(zero, kUnalignedAllocationInNewSpace);
1364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference allocation_top =
1367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AllocationUtils::GetAllocationTopReference(isolate(), flags);
1368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update new top. Use scratch if available.
1370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (scratch.is(no_reg)) {
1371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand::StaticVariable(allocation_top), result_end);
1372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(scratch, 0), result_end);
1374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Allocate(int object_size,
1379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result,
1380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result_end,
1381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register scratch,
1382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* gc_required,
1383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              AllocationFlags flags) {
1384e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1385e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
1386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!FLAG_inline_new) {
1387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (emit_debug_code()) {
1388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Trash the registers to simulate an allocation failure.
1389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(result, Immediate(0x7091));
1390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (result_end.is_valid()) {
1391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        mov(result_end, Immediate(0x7191));
1392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (scratch.is_valid()) {
1394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        mov(scratch, Immediate(0x7291));
1395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    jmp(gc_required);
1398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1400e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result.is(result_end));
1401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load address of new object into result.
1403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadAllocationTopHelper(result, scratch, flags);
1404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference allocation_limit =
1406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Align the next allocation. Storing the filler map without checking top is
1409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // safe in new-space because the limit of the heap is aligned there.
1410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1411e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
1412e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label aligned;
1414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result, Immediate(kDoubleAlignmentMask));
1415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &aligned, Label::kNear);
1416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
1417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cmp(result, Operand::StaticVariable(allocation_limit));
1418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(above_equal, gc_required);
1419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(result, 0),
1421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(isolate()->factory()->one_pointer_filler_map()));
1422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(result, Immediate(kDoubleSize / 2));
1423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&aligned);
1424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate new top and bail out if space is exhausted.
1427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register top_reg = result_end.is_valid() ? result_end : result;
1428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!top_reg.is(result)) {
1429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(top_reg, result);
1430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(top_reg, Immediate(object_size));
1432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(carry, gc_required);
1433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(top_reg, Operand::StaticVariable(allocation_limit));
1434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, gc_required);
1435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update allocation top.
1437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UpdateAllocationTopHelper(top_reg, scratch, flags);
1438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Tag result if requested.
1440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool tag_result = (flags & TAG_OBJECT) != 0;
1441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (top_reg.is(result)) {
1442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (tag_result) {
1443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      sub(result, Immediate(object_size - kHeapObjectTag));
1444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      sub(result, Immediate(object_size));
1446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (tag_result) {
1448e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kHeapObjectTag == 1);
1449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    inc(result);
1450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Allocate(int header_size,
1455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              ScaleFactor element_size,
1456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register element_count,
1457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              RegisterValueType element_count_type,
1458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result,
1459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result_end,
1460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register scratch,
1461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* gc_required,
1462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              AllocationFlags flags) {
1463e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((flags & SIZE_IN_WORDS) == 0);
1464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!FLAG_inline_new) {
1465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (emit_debug_code()) {
1466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Trash the registers to simulate an allocation failure.
1467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(result, Immediate(0x7091));
1468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(result_end, Immediate(0x7191));
1469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (scratch.is_valid()) {
1470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        mov(scratch, Immediate(0x7291));
1471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Register element_count is not modified by the function.
1473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    jmp(gc_required);
1475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1477e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result.is(result_end));
1478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load address of new object into result.
1480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadAllocationTopHelper(result, scratch, flags);
1481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference allocation_limit =
1483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Align the next allocation. Storing the filler map without checking top is
1486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // safe in new-space because the limit of the heap is aligned there.
1487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1488e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
1489e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label aligned;
1491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result, Immediate(kDoubleAlignmentMask));
1492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &aligned, Label::kNear);
1493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
1494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cmp(result, Operand::StaticVariable(allocation_limit));
1495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(above_equal, gc_required);
1496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(result, 0),
1498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(isolate()->factory()->one_pointer_filler_map()));
1499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(result, Immediate(kDoubleSize / 2));
1500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&aligned);
1501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate new top and bail out if space is exhausted.
1504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We assume that element_count*element_size + header_size does not
1505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // overflow.
1506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (element_count_type == REGISTER_VALUE_IS_SMI) {
1507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
1508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
1509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
1510e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(element_size >= times_2);
1511e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kSmiTagSize == 1);
1512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    element_size = static_cast<ScaleFactor>(element_size - 1);
1513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1514e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
1515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(result_end, Operand(element_count, element_size, header_size));
1517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(result_end, result);
1518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(carry, gc_required);
1519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(result_end, Operand::StaticVariable(allocation_limit));
1520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, gc_required);
1521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & TAG_OBJECT) != 0) {
1523e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kHeapObjectTag == 1);
1524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    inc(result);
1525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update allocation top.
1528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UpdateAllocationTopHelper(result_end, scratch, flags);
1529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Allocate(Register object_size,
1533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result,
1534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register result_end,
1535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register scratch,
1536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* gc_required,
1537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              AllocationFlags flags) {
1538e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
1539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!FLAG_inline_new) {
1540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (emit_debug_code()) {
1541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Trash the registers to simulate an allocation failure.
1542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(result, Immediate(0x7091));
1543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(result_end, Immediate(0x7191));
1544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (scratch.is_valid()) {
1545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        mov(scratch, Immediate(0x7291));
1546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // object_size is left unchanged by this function.
1548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    jmp(gc_required);
1550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1552e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result.is(result_end));
1553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load address of new object into result.
1555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadAllocationTopHelper(result, scratch, flags);
1556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference allocation_limit =
1558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Align the next allocation. Storing the filler map without checking top is
1561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // safe in new-space because the limit of the heap is aligned there.
1562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & DOUBLE_ALIGNMENT) != 0) {
1563e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
1564e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
1565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label aligned;
1566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(result, Immediate(kDoubleAlignmentMask));
1567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &aligned, Label::kNear);
1568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
1569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cmp(result, Operand::StaticVariable(allocation_limit));
1570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(above_equal, gc_required);
1571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(result, 0),
1573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(isolate()->factory()->one_pointer_filler_map()));
1574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(result, Immediate(kDoubleSize / 2));
1575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&aligned);
1576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate new top and bail out if space is exhausted.
1579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!object_size.is(result_end)) {
1580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(result_end, object_size);
1581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(result_end, result);
1583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(carry, gc_required);
1584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(result_end, Operand::StaticVariable(allocation_limit));
1585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above, gc_required);
1586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Tag result if requested.
1588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((flags & TAG_OBJECT) != 0) {
1589e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kHeapObjectTag == 1);
1590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    inc(result);
1591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update allocation top.
1594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UpdateAllocationTopHelper(result_end, scratch, flags);
1595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
1599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference new_space_allocation_top =
1600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::new_space_allocation_top_address(isolate());
1601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Make sure the object has no tag before resetting top.
1603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(object, Immediate(~kHeapObjectTagMask));
1604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
1605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(object, Operand::StaticVariable(new_space_allocation_top));
1606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(below, kUndoAllocationOfNonAllocatedMemory);
1607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
1608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(new_space_allocation_top), object);
1609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AllocateHeapNumber(Register result,
1613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Register scratch1,
1614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Register scratch2,
161558a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org                                        Label* gc_required,
161658a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org                                        MutableMode mode) {
1617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate heap number in new space.
1618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
1619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
162158a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org  Handle<Map> map = mode == MUTABLE
162258a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      ? isolate()->factory()->mutable_heap_number_map()
162358a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org      : isolate()->factory()->heap_number_map();
162458a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org
1625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map.
162658a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
1627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AllocateTwoByteString(Register result,
1631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register length,
1632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register scratch1,
1633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register scratch2,
1634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register scratch3,
1635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Label* gc_required) {
1636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate the number of bytes needed for the characters in the string while
1637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // observing object alignment.
1638e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1639e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kShortSize == 2);
1640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // scratch1 = length * 2 + kObjectAlignmentMask.
1641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
1642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch1, Immediate(~kObjectAlignmentMask));
1643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate two byte string in new space.
1645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(SeqTwoByteString::kHeaderSize,
1646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           times_1,
1647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch1,
1648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           REGISTER_VALUE_IS_INT32,
1649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           result,
1650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch2,
1651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch3,
1652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           gc_required,
1653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map, length and hash field.
1656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(isolate()->factory()->string_map()));
1658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, length);
1659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiTag(scratch1);
1660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kHashFieldOffset),
1662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(String::kEmptyHashField));
1663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1666b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
1667b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                           Register scratch1, Register scratch2,
1668b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                           Register scratch3,
1669b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                           Label* gc_required) {
1670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate the number of bytes needed for the characters in the string while
1671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // observing object alignment.
1672e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, length);
1674e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kCharSize == 1);
1675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(scratch1, Immediate(kObjectAlignmentMask));
1676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch1, Immediate(~kObjectAlignmentMask));
1677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1678b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Allocate one-byte string in new space.
1679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(SeqOneByteString::kHeaderSize,
1680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           times_1,
1681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch1,
1682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           REGISTER_VALUE_IS_INT32,
1683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           result,
1684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch2,
1685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch3,
1686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           gc_required,
1687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map, length and hash field.
1690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1691b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Immediate(isolate()->factory()->one_byte_string_map()));
1692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, length);
1693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiTag(scratch1);
1694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kLengthOffset), scratch1);
1695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kHashFieldOffset),
1696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(String::kEmptyHashField));
1697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1700b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::AllocateOneByteString(Register result, int length,
1701b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                           Register scratch1, Register scratch2,
1702b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                           Label* gc_required) {
1703e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(length > 0);
1704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1705b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Allocate one-byte string in new space.
1706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
1707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           gc_required, TAG_OBJECT);
1708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map, length and hash field.
1710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1711b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Immediate(isolate()->factory()->one_byte_string_map()));
1712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kLengthOffset),
1713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(Smi::FromInt(length)));
1714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, String::kHashFieldOffset),
1715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(String::kEmptyHashField));
1716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AllocateTwoByteConsString(Register result,
1720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Register scratch1,
1721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Register scratch2,
1722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Label* gc_required) {
1723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate heap number in new space.
1724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
1725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map. The other fields are left uninitialized.
1728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(isolate()->factory()->cons_string_map()));
1730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1733b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::AllocateOneByteConsString(Register result,
1734b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                               Register scratch1,
1735b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                               Register scratch2,
1736b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                               Label* gc_required) {
1737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(ConsString::kSize,
1738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           result,
1739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch1,
1740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           scratch2,
1741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           gc_required,
17427e6132b924829c353864933f29124419916db550machenbach@chromium.org           TAG_OBJECT);
1743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map. The other fields are left uninitialized.
1745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1746b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Immediate(isolate()->factory()->cons_one_byte_string_map()));
1747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
1751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Register scratch1,
1752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Register scratch2,
1753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          Label* gc_required) {
1754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate heap number in new space.
1755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map. The other fields are left uninitialized.
1759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(isolate()->factory()->sliced_string_map()));
1761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1764b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
1765b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                 Register scratch1,
1766b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                 Register scratch2,
1767b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                 Label* gc_required) {
1768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate heap number in new space.
1769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
1770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           TAG_OBJECT);
1771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the map. The other fields are left uninitialized.
1773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(FieldOperand(result, HeapObject::kMapOffset),
1774b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      Immediate(isolate()->factory()->sliced_one_byte_string_map()));
1775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copy memory, byte-by-byte, from source to destination.  Not optimized for
1779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// long or aligned copies.  The contents of scratch and length are destroyed.
1780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Source and destination are incremented by length.
1781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Many variants of movsb, loop unrolling, word moves, and indexed operands
1782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// have been tried here already, and this is fastest.
1783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// A simpler loop is faster on small copies, but 30% slower on large ones.
1784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// The cld() instruction must have been emitted, to set the direction flag(),
1785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// before calling this function.
1786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CopyBytes(Register source,
1787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register destination,
1788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register length,
1789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register scratch) {
1790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label short_loop, len4, len8, len12, done, short_string;
1791e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(source.is(esi));
1792e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(destination.is(edi));
1793e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(length.is(ecx));
1794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(length, Immediate(4));
1795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below, &short_string, Label::kNear);
1796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Because source is 4-byte aligned in our uses of this function,
1798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // we keep source aligned for the rep_movs call by copying the odd bytes
1799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // at the end of the ranges.
1800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(source, length, times_1, -4));
1801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(destination, length, times_1, -4), scratch);
1802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(length, Immediate(8));
1804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below_equal, &len4, Label::kNear);
1805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(length, Immediate(12));
1806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below_equal, &len8, Label::kNear);
1807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(length, Immediate(16));
1808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below_equal, &len12, Label::kNear);
1809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, ecx);
1811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(ecx, 2);
1812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  rep_movs();
1813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch, Immediate(0x3));
1814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(destination, scratch);
1815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&done, Label::kNear);
1816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&len12);
1818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(source, 8));
1819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(destination, 8), scratch);
1820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&len8);
1821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(source, 4));
1822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(destination, 4), scratch);
1823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&len4);
1824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(source, 0));
1825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(destination, 0), scratch);
1826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(destination, length);
1827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&done, Label::kNear);
1828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&short_string);
1830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(length, length);
1831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &done, Label::kNear);
1832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&short_loop);
1834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov_b(scratch, Operand(source, 0));
1835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov_b(Operand(destination, 0), scratch);
1836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  inc(source);
1837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  inc(destination);
1838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  dec(length);
1839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, &short_loop);
1840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
1842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
1846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                Register end_offset,
1847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                Register filler) {
1848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label loop, entry;
1849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&entry);
1850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&loop);
1851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(start_offset, 0), filler);
1852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(start_offset, Immediate(kPointerSize));
1853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&entry);
1854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(start_offset, end_offset);
1855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(less, &loop);
1856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::BooleanBitTest(Register object,
1860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    int field_offset,
1861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    int bit_index) {
1862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bit_index += kSmiTagSize + kSmiShiftSize;
18639aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte));
1864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int byte_index = bit_index / kBitsPerByte;
1865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int byte_bit_index = bit_index & (kBitsPerByte - 1);
1866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test_b(FieldOperand(object, field_offset + byte_index),
1867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         static_cast<byte>(1 << byte_bit_index));
1868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::NegativeZeroTest(Register result,
1873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Register op,
1874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Label* then_label) {
1875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label ok;
1876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(result, result);
1877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, &ok);
1878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(op, op);
1879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(sign, then_label);
1880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&ok);
1881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::NegativeZeroTest(Register result,
1885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Register op1,
1886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Register op2,
1887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Register scratch,
1888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Label* then_label) {
1889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label ok;
1890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(result, result);
1891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, &ok);
1892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, op1);
1893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  or_(scratch, op2);
1894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(sign, then_label);
1895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&ok);
1896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TryGetFunctionPrototype(Register function,
1900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register result,
1901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register scratch,
1902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Label* miss,
1903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             bool miss_on_bound_function) {
1904f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org  Label non_instance;
1905f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org  if (miss_on_bound_function) {
1906f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // Check that the receiver isn't a smi.
1907f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    JumpIfSmi(function, miss);
1908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1909f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // Check that the function really is a function.
1910f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    CmpObjectType(function, JS_FUNCTION_TYPE, result);
1911f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    j(not_equal, miss);
1912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If a bound function, go to miss label.
1914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch,
1915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
1916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    BooleanBitTest(scratch, SharedFunctionInfo::kCompilerHintsOffset,
1917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   SharedFunctionInfo::kBoundFunction);
1918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(not_zero, miss);
1919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1920f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // Make sure that the function has an instance prototype.
1921f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
1922f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
1923f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    j(not_zero, &non_instance);
1924f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org  }
1925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the prototype or initial map from the function.
1927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(result,
1928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the prototype or initial map is the hole, don't return it and
1931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // simply miss the cache instead. This will allow us to allocate a
1932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // prototype object on-demand in the runtime system.
1933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(result, Immediate(isolate()->factory()->the_hole_value()));
1934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, miss);
1935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the function does not have an initial map, we're done.
1937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
1938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CmpObjectType(result, MAP_TYPE, scratch);
1939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &done);
1940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the prototype from the initial map.
1942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(result, FieldOperand(result, Map::kPrototypeOffset));
1943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1944f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org  if (miss_on_bound_function) {
1945f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    jmp(&done);
1946f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org
1947f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // Non-instance prototype: Fetch prototype from constructor field
1948f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // in initial map.
1949f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    bind(&non_instance);
1950f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    mov(result, FieldOperand(result, Map::kConstructorOffset));
1951f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org  }
1952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // All done.
1954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
1955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
1959e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
1960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TailCallStub(CodeStub* stub) {
1965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
1966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StubReturn(int argc) {
1970e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(argc >= 1 && generating_stub());
1971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ret((argc - 1) * kPointerSize);
1972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
1976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return has_frame_ || !stub->SometimesSetsUpAFrame();
1977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
1981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The assert checks that the constants for the maximum number of digits
1982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // for an array index cached in the hash field and the number of bits
1983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // reserved for it does not conflict.
1984e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
1985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         (1 << String::kArrayIndexValueBits));
1986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!index.is(hash)) {
1987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(index, hash);
1988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1989e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
1990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
199306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
199406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                 SaveFPRegsMode save_doubles) {
1995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the expected number of arguments of the runtime function is
1996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // constant, we check that the actual number of arguments match the
1997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // expectation.
1998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CHECK(f->nargs < 0 || f->nargs == num_arguments);
1999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(1236192): Most runtime routines don't need the number of
2001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // arguments passed in because it is constant. At some point we
2002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // should remove this need and make the runtime routine entry code
2003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // smarter.
2004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Move(eax, Immediate(num_arguments));
2005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, Immediate(ExternalReference(f, isolate())));
200606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  CEntryStub ces(isolate(), 1, save_doubles);
2007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStub(&ces);
2008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CallExternalReference(ExternalReference ref,
2012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           int num_arguments) {
2013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, Immediate(num_arguments));
2014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, Immediate(ref));
2015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CEntryStub stub(isolate(), 1);
2017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallStub(&stub);
2018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
2022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               int num_arguments,
2023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               int result_size) {
2024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(1236192): Most runtime routines don't need the number of
2025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // arguments passed in because it is constant. At some point we
2026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // should remove this need and make the runtime routine entry code
2027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // smarter.
2028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Move(eax, Immediate(num_arguments));
2029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpToExternalReference(ext);
2030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
2034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     int num_arguments,
2035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     int result_size) {
2036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  TailCallExternalReference(ExternalReference(fid, isolate()),
2037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            num_arguments,
2038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            result_size);
2039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand ApiParameterOperand(int index) {
2043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return Operand(esp, index * kPointerSize);
2044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::PrepareCallApiFunction(int argc) {
2048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EnterApiExitFrame(argc);
2049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
2050e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    mov(esi, Immediate(bit_cast<int32_t>(kZapValue)));
2051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CallApiFunctionAndReturn(
2056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register function_address,
2057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ExternalReference thunk_ref,
2058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand thunk_last_arg,
2059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int stack_space,
2060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand return_value_operand,
2061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand* context_restore_operand) {
2062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference next_address =
2063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::handle_scope_next_address(isolate());
2064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference limit_address =
2065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::handle_scope_limit_address(isolate());
2066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference level_address =
2067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::handle_scope_level_address(isolate());
2068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2069e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(edx.is(function_address));
2070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate HandleScope in callee-save registers.
2071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, Operand::StaticVariable(next_address));
2072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(edi, Operand::StaticVariable(limit_address));
2073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(Operand::StaticVariable(level_address), Immediate(1));
2074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_log_timer_events) {
2076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FrameScope frame(this, StackFrame::MANUAL);
2077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PushSafepointRegisters();
2078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareCallCFunction(1, eax);
2079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(esp, 0),
2080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(ExternalReference::isolate_address(isolate())));
2081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
2082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PopSafepointRegisters();
2083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label profiler_disabled;
2087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label end_profiler_check;
2088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, Immediate(ExternalReference::is_profiling_address(isolate())));
2089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(Operand(eax, 0), 0);
2090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &profiler_disabled);
2091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Additional parameter is the address of the actual getter function.
2093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(thunk_last_arg, function_address);
2094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call the api function.
2095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, Immediate(thunk_ref));
2096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(eax);
2097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&end_profiler_check);
2098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&profiler_disabled);
2100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Call the api function.
2101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(function_address);
2102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&end_profiler_check);
2103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_log_timer_events) {
2105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FrameScope frame(this, StackFrame::MANUAL);
2106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PushSafepointRegisters();
2107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PrepareCallCFunction(1, eax);
2108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(esp, 0),
2109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(ExternalReference::isolate_address(isolate())));
2110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
2111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PopSafepointRegisters();
2112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label prologue;
2115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the value from ReturnValue
2116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, return_value_operand);
2117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label promote_scheduled_exception;
2119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label exception_handled;
2120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label delete_allocated_handles;
2121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label leave_exit_frame;
2122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&prologue);
2124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // No more valid handles (the result handle was the last one). Restore
2125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // previous handle scope.
2126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(next_address), ebx);
2127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sub(Operand::StaticVariable(level_address), Immediate(1));
2128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Assert(above_equal, kInvalidHandleScopeLevel);
2129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(edi, Operand::StaticVariable(limit_address));
2130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &delete_allocated_handles);
2131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&leave_exit_frame);
2132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the function scheduled an exception.
2134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference scheduled_exception_address =
2135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::scheduled_exception_address(isolate());
2136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(Operand::StaticVariable(scheduled_exception_address),
2137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(isolate()->factory()->the_hole_value()));
2138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &promote_scheduled_exception);
2139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&exception_handled);
2140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if ENABLE_EXTRA_CHECKS
2142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the function returned a valid JavaScript value.
2143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label ok;
2144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register return_value = eax;
2145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register map = ecx;
2146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfSmi(return_value, &ok, Label::kNear);
2148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
2149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CmpInstanceType(map, FIRST_NONSTRING_TYPE);
2151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(below, &ok, Label::kNear);
2152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
2154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(above_equal, &ok, Label::kNear);
2155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(map, isolate()->factory()->heap_number_map());
2157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &ok, Label::kNear);
2158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(return_value, isolate()->factory()->undefined_value());
2160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &ok, Label::kNear);
2161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(return_value, isolate()->factory()->true_value());
2163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &ok, Label::kNear);
2164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(return_value, isolate()->factory()->false_value());
2166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &ok, Label::kNear);
2167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(return_value, isolate()->factory()->null_value());
2169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &ok, Label::kNear);
2170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Abort(kAPICallReturnedInvalidObject);
2172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&ok);
2174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
2175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool restore_context = context_restore_operand != NULL;
2177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (restore_context) {
2178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(esi, *context_restore_operand);
2179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LeaveApiExitFrame(!restore_context);
2181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ret(stack_space * kPointerSize);
2182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&promote_scheduled_exception);
2184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  {
2185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FrameScope frame(this, StackFrame::INTERNAL);
218647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    CallRuntime(Runtime::kPromoteScheduledException, 0);
2187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&exception_handled);
2189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // HandleScope limit has changed. Delete allocated extensions.
2191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference delete_extensions =
2192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::delete_handle_scope_extensions(isolate());
2193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&delete_allocated_handles);
2194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand::StaticVariable(limit_address), edi);
2195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(edi, eax);
2196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(Operand(esp, 0),
2197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(ExternalReference::isolate_address(isolate())));
2198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, Immediate(delete_extensions));
2199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(eax);
2200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, edi);
2201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&leave_exit_frame);
2202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
2206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the entry point and jump to the C entry runtime stub.
2207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, Immediate(ext));
2208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CEntryStub ces(isolate(), 1);
2209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
2210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& actual,
2215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    Handle<Code> code_constant,
2216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const Operand& code_operand,
2217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    Label* done,
2218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    bool* definitely_mismatches,
2219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    InvokeFlag flag,
2220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    Label::Distance done_near,
2221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const CallWrapper& call_wrapper) {
2222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool definitely_matches = false;
2223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  *definitely_mismatches = false;
2224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label invoke;
2225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (expected.is_immediate()) {
2226e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(actual.is_immediate());
2227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (expected.immediate() == actual.immediate()) {
2228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      definitely_matches = true;
2229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(eax, actual.immediate());
2231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
2232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.immediate() == sentinel) {
2233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Don't worry about adapting arguments for builtins that
2234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // don't want that done. Skip adaption code by making it look
2235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // like we have a match between expected and actual number of
2236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // arguments.
2237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        definitely_matches = true;
2238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
2239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        *definitely_mismatches = true;
2240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        mov(ebx, expected.immediate());
2241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (actual.is_immediate()) {
2245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Expected is in register, actual is immediate. This is the
2246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // case when we invoke function values without going through the
2247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // IC mechanism.
2248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cmp(expected.reg(), actual.immediate());
2249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(equal, &invoke);
2250e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(expected.reg().is(ebx));
2251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(eax, actual.immediate());
2252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (!expected.reg().is(actual.reg())) {
2253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Both expected and actual are in (different) registers. This
2254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // is the case when we invoke functions using call and apply.
2255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cmp(expected.reg(), actual.reg());
2256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      j(equal, &invoke);
2257e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(actual.reg().is(eax));
2258e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(expected.reg().is(ebx));
2259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!definitely_matches) {
2263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Code> adaptor =
2264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->builtins()->ArgumentsAdaptorTrampoline();
2265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!code_constant.is_null()) {
2266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(edx, Immediate(code_constant));
2267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (!code_operand.is_reg(edx)) {
2269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(edx, code_operand);
2270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (flag == CALL_FUNCTION) {
2273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
2274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call(adaptor, RelocInfo::CODE_TARGET);
2275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call_wrapper.AfterCall();
2276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!*definitely_mismatches) {
2277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        jmp(done, done_near);
2278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      jmp(adaptor, RelocInfo::CODE_TARGET);
2281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&invoke);
2283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokeCode(const Operand& code,
2288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                const ParameterCount& expected,
2289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                const ParameterCount& actual,
2290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                InvokeFlag flag,
2291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                const CallWrapper& call_wrapper) {
2292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // You can't call a function without a valid frame.
2293e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(flag == JUMP_FUNCTION || has_frame());
2294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
2296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool definitely_mismatches = false;
2297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InvokePrologue(expected, actual, Handle<Code>::null(), code,
2298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                 &done, &definitely_mismatches, flag, Label::kNear,
2299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                 call_wrapper);
2300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!definitely_mismatches) {
2301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (flag == CALL_FUNCTION) {
2302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call_wrapper.BeforeCall(CallSize(code));
2303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call(code);
2304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      call_wrapper.AfterCall();
2305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2306e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(flag == JUMP_FUNCTION);
2307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      jmp(code);
2308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&done);
2310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokeFunction(Register fun,
2315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& actual,
2316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    InvokeFlag flag,
2317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const CallWrapper& call_wrapper) {
2318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // You can't call a function without a valid frame.
2319e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(flag == JUMP_FUNCTION || has_frame());
2320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2321e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(fun.is(edi));
2322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
2325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiUntag(ebx);
2326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ParameterCount expected(ebx);
2328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             expected, actual, flag, call_wrapper);
2330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokeFunction(Register fun,
2334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& expected,
2335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& actual,
2336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    InvokeFlag flag,
2337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const CallWrapper& call_wrapper) {
2338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // You can't call a function without a valid frame.
2339e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(flag == JUMP_FUNCTION || has_frame());
2340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2341e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(fun.is(edi));
2342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             expected, actual, flag, call_wrapper);
2346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& expected,
2351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const ParameterCount& actual,
2352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    InvokeFlag flag,
2353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const CallWrapper& call_wrapper) {
2354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadHeapObject(edi, function);
2355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InvokeFunction(edi, expected, actual, flag, call_wrapper);
2356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
2360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   InvokeFlag flag,
2361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   const CallWrapper& call_wrapper) {
2362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // You can't call a builtin without a valid frame.
2363e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(flag == JUMP_FUNCTION || has_frame());
2364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Rely on the assertion to check that the number of provided
2366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // arguments match the expected number of arguments. Fake a
2367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // parameter count to avoid emitting code to do the check.
2368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ParameterCount expected(0);
2369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GetBuiltinFunction(edi, id);
2370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             expected, expected, flag, call_wrapper);
2372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::GetBuiltinFunction(Register target,
2376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Builtins::JavaScript id) {
2377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the JavaScript builtin function from the builtins object.
2378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
2380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(target, FieldOperand(target,
2381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
2382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
2386e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!target.is(edi));
2387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the JavaScript builtin function from the builtins object.
2388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GetBuiltinFunction(edi, id);
2389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the code entry point from the function into the target register.
2390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (context_chain_length > 0) {
2396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Move up the chain of contexts to the context containing the slot.
2397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 1; i < context_chain_length; i++) {
2399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Slot is in the current function context.  Move it into the
2403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // destination register in case we store into it (the write barrier
2404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // cannot be allowed to destroy the context in esi).
2405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, esi);
2406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // We should not have found a with context by walking the context chain
2409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // (i.e., the static scope chain and runtime context chain do not agree).
2410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // A variable occurring in such a scope should have slot type LOOKUP and
2411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // not CONTEXT.
2412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
2413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(dst, HeapObject::kMapOffset),
2414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->factory()->with_context_map());
2415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(not_equal, kVariableResolvedToWithContext);
2416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadTransitionedArrayMapConditional(
2421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ElementsKind expected_kind,
2422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ElementsKind transitioned_kind,
2423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register map_in_out,
2424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch,
2425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* no_map_match) {
2426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the global or builtins object from the current context.
2427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
2429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the function's map is the same as the expected cached map.
2431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, Operand(scratch,
2432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
2433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  size_t offset = expected_kind * kPointerSize +
2435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FixedArrayBase::kHeaderSize;
2436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(map_in_out, FieldOperand(scratch, offset));
2437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, no_map_match);
2438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Use the transitioned cached map.
2440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  offset = transitioned_kind * kPointerSize +
2441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FixedArrayBase::kHeaderSize;
2442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map_in_out, FieldOperand(scratch, offset));
2443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
2447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the global or builtins object from the current context.
2448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(function,
2449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the native context from the global or builtins object.
2451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(function,
2452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(function, GlobalObject::kNativeContextOffset));
2453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the function from the native context.
2454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(function, Operand(function, Context::SlotOffset(index)));
2455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
2459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                  Register map) {
2460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the initial map.  The global functions all have initial maps.
2461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
2463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok, fail;
2464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
2465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    jmp(&ok);
2466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&fail);
2467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Abort(kGlobalFunctionsMustHaveInitialMap);
2468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
2469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Store the value in register src in the safepoint register stack
2474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// slot for register dst.
2475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
2476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(SafepointRegisterSlot(dst), src);
2477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
2481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(SafepointRegisterSlot(dst), src);
2482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
2486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(dst, SafepointRegisterSlot(src));
2487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
2491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
2492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
2496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The registers are pushed starting with the lowest encoding,
2497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // which means that lowest encodings are furthest away from
2498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the stack pointer.
2499e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
2500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return kNumSafepointRegisters - reg_code - 1;
2501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadHeapObject(Register result,
2505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    Handle<HeapObject> object) {
2506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllowDeferredHandleDereference embedding_raw_address;
2507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate()->heap()->InNewSpace(*object)) {
2508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(result, Operand::ForCell(cell));
2510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(result, object);
2512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
2517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllowDeferredHandleDereference using_raw_address;
2518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate()->heap()->InNewSpace(*object)) {
2519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(reg, Operand::ForCell(cell));
2521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(reg, object);
2523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
2528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllowDeferredHandleDereference using_raw_address;
2529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate()->heap()->InNewSpace(*object)) {
2530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(Operand::ForCell(cell));
2532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Push(object);
2534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Ret() {
2539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ret(0);
2540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
2544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (is_uint16(bytes_dropped)) {
2545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ret(bytes_dropped);
2546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pop(scratch);
2548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(esp, Immediate(bytes_dropped));
2549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(scratch);
2550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ret(0);
2551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::VerifyX87StackDepth(uint32_t depth) {
2556a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Turn off the stack depth check when serializer is enabled to reduce the
2557a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // code size.
2558a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  if (serializer_enabled()) return;
2559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Make sure the floating point stack is either empty or has depth items.
2560e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(depth <= 7);
2561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // This is very expensive.
2562e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(FLAG_debug_code && FLAG_enable_slow_asserts);
2563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The top-of-stack (tos) is 7 if there is one item pushed.
2565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int tos = (8 - depth) % 8;
2566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kTopMask = 0x3800;
2567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(eax);
2568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fwait();
2569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fnstsw_ax();
2570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(eax, kTopMask);
2571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(eax, 11);
2572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(eax, Immediate(tos));
2573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(equal, kUnexpectedFPUStackDepthAfterInstruction);
2574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fnclex();
2575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(eax);
2576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Drop(int stack_elements) {
2580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (stack_elements > 0) {
2581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(esp, Immediate(stack_elements * kPointerSize));
2582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Move(Register dst, Register src) {
2587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!dst.is(src)) {
2588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, src);
2589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Move(Register dst, const Immediate& x) {
2594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (x.is_zero()) {
2595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
2596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(dst, x);
2598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Move(const Operand& dst, const Immediate& x) {
2603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(dst, x);
2604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
2609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
2610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2615e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value > 0);
2616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
2617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (value == 1) {
2619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      inc(operand);
2620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      add(operand, Immediate(value));
2622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2628e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value > 0);
2629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
2630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand operand = Operand::StaticVariable(ExternalReference(counter));
2631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (value == 1) {
2632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      dec(operand);
2633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      sub(operand, Immediate(value));
2635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::IncrementCounter(Condition cc,
2641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      StatsCounter* counter,
2642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      int value) {
2643e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value > 0);
2644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
2645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label skip;
2646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(NegateCondition(cc), &skip);
2647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pushfd();
2648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    IncrementCounter(counter, value);
2649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    popfd();
2650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&skip);
2651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::DecrementCounter(Condition cc,
2656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      StatsCounter* counter,
2657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      int value) {
2658e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value > 0);
2659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_native_code_counters && counter->Enabled()) {
2660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label skip;
2661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(NegateCondition(cc), &skip);
2662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pushfd();
2663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DecrementCounter(counter, value);
2664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    popfd();
2665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&skip);
2666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
2671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) Check(cc, reason);
2672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::AssertFastElements(Register elements) {
2676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
2677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Factory* factory = isolate()->factory();
2678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
2679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(factory->fixed_array_map()));
2681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &ok);
2682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(factory->fixed_double_array_map()));
2684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &ok);
2685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(FieldOperand(elements, HeapObject::kMapOffset),
2686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Immediate(factory->fixed_cow_array_map()));
2687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(equal, &ok);
2688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Abort(kJSObjectWithFastElementsMapHasSlowElements);
2689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
2690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
2695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label L;
2696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(cc, &L);
2697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Abort(reason);
2698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // will not return here
2699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&L);
2700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckStackAlignment() {
27045de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  int frame_alignment = base::OS::ActivationFrameAlignment();
2705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int frame_alignment_mask = frame_alignment - 1;
2706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (frame_alignment > kPointerSize) {
27079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
2708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label alignment_as_expected;
2709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(esp, Immediate(frame_alignment_mask));
2710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &alignment_as_expected);
2711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Abort if stack is not aligned.
2712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
2713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&alignment_as_expected);
2714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::Abort(BailoutReason reason) {
2719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
2720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const char* msg = GetBailoutReason(reason);
2721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (msg != NULL) {
2722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordComment("Abort message: ");
2723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordComment(msg);
2724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_trap_on_abort) {
2727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
2728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
2729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
2731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(reason))));
2733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Disable stub call restrictions to always allow calls to abort.
2734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!has_frame_) {
2735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We don't actually want to generate a pile of code for this, so just
2736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // claim there is a stack frame, without generating one.
2737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    FrameScope scope(this, StackFrame::NONE);
2738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallRuntime(Runtime::kAbort, 1);
2739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallRuntime(Runtime::kAbort, 1);
2741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // will not return here
2743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int3();
2744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LoadInstanceDescriptors(Register map,
2748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register descriptors) {
2749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
2750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
2754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(dst, FieldOperand(map, Map::kBitField3Offset));
2755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
2756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::LookupNumberStringCache(Register object,
2760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register result,
2761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register scratch1,
2762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Register scratch2,
2763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                             Label* not_found) {
2764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Use of registers. Register result is used as a temporary.
2765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register number_string_cache = result;
2766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register mask = scratch1;
2767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = scratch2;
2768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the number string cache.
2770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
2771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Make the hash mask from the length of the number string cache. It
2772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // contains two elements (number and string) for each cache entry.
2773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
2774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(mask, kSmiTagSize + 1);  // Untag length and divide it by two.
2775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  sub(mask, Immediate(1));  // Make mask.
2776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Calculate the entry in the number string cache. The hash value in the
2778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // number string cache for smis is just the smi value, and the hash for
2779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // doubles is the xor of the upper and lower words. See
2780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Heap::GetNumberStringCache.
2781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label smi_hash_calculated;
2782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label load_result_from_cache;
2783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label not_smi;
2784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfNotSmi(object, &not_smi, Label::kNear);
2786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, object);
2787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiUntag(scratch);
2788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&smi_hash_calculated, Label::kNear);
2789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&not_smi);
2790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(FieldOperand(object, HeapObject::kMapOffset),
2791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      isolate()->factory()->heap_number_map());
2792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, not_found);
2793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(8 == kDoubleSize);
2794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
2795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
2796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Object is heap number and hash is now in scratch. Calculate cache index.
2797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch, mask);
2798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = scratch;
2799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register probe = mask;
2800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(probe,
2801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(number_string_cache,
2802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   index,
2803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   times_twice_pointer_size,
2804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   FixedArray::kHeaderSize));
2805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfSmi(probe, not_found);
2806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld_d(FieldOperand(object, HeapNumber::kValueOffset));
2807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
2808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  FCmp();
2809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(parity_even, not_found);  // Bail out if NaN is involved.
2810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, not_found);  // The cache did not contain this value.
2811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&load_result_from_cache, Label::kNear);
2812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&smi_hash_calculated);
2814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Object is smi and hash is now in scratch. Calculate cache index.
2815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch, mask);
2816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the entry is the smi we are looking for.
2817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(object,
2818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(number_string_cache,
2819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   index,
2820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   times_twice_pointer_size,
2821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   FixedArray::kHeaderSize));
2822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, not_found);
2823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the result from the cache.
2825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&load_result_from_cache);
2826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(result,
2827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FieldOperand(number_string_cache,
2828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   index,
2829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   times_twice_pointer_size,
2830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   FixedArray::kHeaderSize + kPointerSize));
2831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
2832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2835b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
2836b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    Register instance_type, Register scratch, Label* failure) {
2837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!scratch.is(instance_type)) {
2838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, instance_type);
2839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch,
2841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag);
2843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, failure);
2844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2847b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register object1,
2848b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                           Register object2,
2849b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                           Register scratch1,
2850b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                           Register scratch2,
2851b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                                           Label* failure) {
2852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that both objects are not smis.
2853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, object1);
2855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(scratch1, object2);
2856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfSmi(scratch1, failure);
2857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load instance type for both strings.
2859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2864b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Check that both are flat one-byte strings.
2865b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  const int kFlatOneByteStringMask =
2866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2867b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  const int kFlatOneByteStringTag =
2868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      kStringTag | kOneByteStringTag | kSeqStringTag;
2869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Interleave bits from both instance types and compare them in one check.
2870b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2871b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  and_(scratch1, kFlatOneByteStringMask);
2872b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  and_(scratch2, kFlatOneByteStringMask);
2873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2874b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  cmp(scratch1, kFlatOneByteStringTag | (kFlatOneByteStringTag << 3));
2875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, failure);
2876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
287906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
288006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                                     Label* not_unique_name,
288106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                                     Label::Distance distance) {
2882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label succeed;
2884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &succeed);
2886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmpb(operand, static_cast<uint8_t>(SYMBOL_TYPE));
2887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, not_unique_name, distance);
2888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&succeed);
2890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
2894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               Register index,
2895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               Register value,
2896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               uint32_t encoding_mask) {
2897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label is_object;
2898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  JumpIfNotSmi(string, &is_object, Label::kNear);
2899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Abort(kNonObject);
2900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&is_object);
2901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  push(value);
2903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(value, FieldOperand(string, HeapObject::kMapOffset));
2904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
2905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
2907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(value, Immediate(encoding_mask));
2908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop(value);
2909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(equal, kUnexpectedStringType);
2910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The index is assumed to be untagged coming in, tag it to compare with the
2912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // string length without using a temp register, it is restored at the end of
2913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // this function.
2914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiTag(index);
2915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(no_overflow, kIndexIsTooLarge);
2916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(index, FieldOperand(string, String::kLengthOffset));
2918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(less, kIndexIsTooLarge);
2919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(index, Immediate(Smi::FromInt(0)));
2921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Check(greater_equal, kIndexIsNegative);
2922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore the index
2924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiUntag(index);
2925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
29295de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  int frame_alignment = base::OS::ActivationFrameAlignment();
2930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (frame_alignment != 0) {
2931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Make stack end at alignment and make room for num_arguments words
2932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // and the original value of esp.
2933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, esp);
2934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    sub(esp, Immediate((num_arguments + 1) * kPointerSize));
29359aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
2936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(esp, -frame_alignment);
2937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(Operand(esp, num_arguments * kPointerSize), scratch);
2938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    sub(esp, Immediate(num_arguments * kPointerSize));
2940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CallCFunction(ExternalReference function,
2945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   int num_arguments) {
2946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Trashing eax is ok as it will be the return value.
2947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, Immediate(function));
2948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCFunction(eax, num_arguments);
2949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CallCFunction(Register function,
2953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   int num_arguments) {
2954e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(has_frame());
2955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check stack alignment.
2956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
2957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CheckStackAlignment();
2958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  call(function);
29615de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  if (base::OS::ActivationFrameAlignment() != 0) {
2962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(esp, Operand(esp, num_arguments * kPointerSize));
2963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(esp, Immediate(num_arguments * kPointerSize));
2965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2969d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org#ifdef DEBUG
2970d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.orgbool AreAliased(Register reg1,
2971d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg2,
2972d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg3,
2973d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg4,
2974d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg5,
2975d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg6,
2976d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg7,
2977d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                Register reg8) {
2978d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
2979d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
2980d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      reg7.is_valid() + reg8.is_valid();
2981d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
2982d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  RegList regs = 0;
2983d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg1.is_valid()) regs |= reg1.bit();
2984d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg2.is_valid()) regs |= reg2.bit();
2985d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg3.is_valid()) regs |= reg3.bit();
2986d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg4.is_valid()) regs |= reg4.bit();
2987d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg5.is_valid()) regs |= reg5.bit();
2988d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg6.is_valid()) regs |= reg6.bit();
2989d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg7.is_valid()) regs |= reg7.bit();
2990d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  if (reg8.is_valid()) regs |= reg8.bit();
2991d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  int n_of_non_aliasing_regs = NumRegs(regs);
2992d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
2993d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  return n_of_valid_regs != n_of_non_aliasing_regs;
2994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2995d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org#endif
2996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCodePatcher::CodePatcher(byte* address, int size)
2999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    : address_(address),
3000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      size_(size),
3001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      masm_(NULL, address, size + Assembler::kGap) {
3002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Create a new macro assembler pointing to the address of the code to patch.
3003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The size is adjusted with kGap on order for the assembler to generate size
3004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // bytes of instructions without failing with buffer size constraints.
3005e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCodePatcher::~CodePatcher() {
3010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Indicate that code has changed.
30115de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CpuFeatures::FlushICache(address_, size_);
3012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the code was patched as expected.
3014e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(masm_.pc_ == address_ + size_);
3015e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckPageFlag(
3020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object,
3021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch,
3022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int mask,
3023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Condition cc,
3024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* condition_met,
3025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label::Distance condition_met_distance) {
3026e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cc == zero || cc == not_zero);
3027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (scratch.is(object)) {
3028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(scratch, Immediate(~Page::kPageAlignmentMask));
3029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, Immediate(~Page::kPageAlignmentMask));
3031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(scratch, object);
3032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (mask < (1 << kBitsPerByte)) {
3034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
3035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           static_cast<uint8_t>(mask));
3036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
3038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(cc, condition_met, condition_met_distance);
3040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckPageFlagForMap(
3044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Map> map,
3045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int mask,
3046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Condition cc,
3047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* condition_met,
3048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label::Distance condition_met_distance) {
3049e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cc == zero || cc == not_zero);
3050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Page* page = Page::FromAddress(map->address());
30519d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  DCHECK(!serializer_enabled());  // Serializer cannot match page_flags.
3052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference reference(ExternalReference::page_flags(page));
3053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The inlined static address check of the page's flags relies
3054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // on maps never being compacted.
3055e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!isolate()->heap()->mark_compact_collector()->
3056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         IsOnEvacuationCandidate(*map));
3057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (mask < (1 << kBitsPerByte)) {
3058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask));
3059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(Operand::StaticVariable(reference), Immediate(mask));
3061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(cc, condition_met, condition_met_distance);
3063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckMapDeprecated(Handle<Map> map,
3067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Register scratch,
3068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        Label* if_deprecated) {
3069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (map->CanBeDeprecated()) {
3070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, map);
3071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(scratch, FieldOperand(scratch, Map::kBitField3Offset));
3072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    and_(scratch, Immediate(Map::Deprecated::kMask));
3073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(not_zero, if_deprecated);
3074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::JumpIfBlack(Register object,
3079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register scratch0,
3080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register scratch1,
3081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Label* on_black,
3082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Label::Distance on_black_near) {
3083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HasColor(object, scratch0, scratch1,
3084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           on_black, on_black_near,
3085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           1, 0);  // kBlackBitPattern.
3086e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
3087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::HasColor(Register object,
3091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register bitmap_scratch,
3092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register mask_scratch,
3093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label* has_color,
3094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Label::Distance has_color_distance,
3095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              int first_bit,
3096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              int second_bit) {
3097e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
3098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GetMarkBits(object, bitmap_scratch, mask_scratch);
3100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label other_color, word_boundary;
3102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
3104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
3105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &word_boundary, Label::kNear);
3106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
3108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&other_color, Label::kNear);
3109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&word_boundary);
3111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1);
3112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
3114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&other_color);
3115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::GetMarkBits(Register addr_reg,
3119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register bitmap_reg,
3120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register mask_reg) {
3121e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
3122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
3123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(bitmap_reg, addr_reg);
3124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, addr_reg);
3125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int shift =
3126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
3127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(ecx, shift);
3128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(ecx,
3129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
3130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(bitmap_reg, ecx);
3132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, addr_reg);
3133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(ecx, kPointerSizeLog2);
3134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
3135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(mask_reg, Immediate(1));
3136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shl_cl(mask_reg);
3137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EnsureNotWhite(
3141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value,
3142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register bitmap_scratch,
3143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register mask_scratch,
3144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* value_is_white_and_not_data,
3145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label::Distance distance) {
3146e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
3147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GetMarkBits(value, bitmap_scratch, mask_scratch);
3148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the value is black or grey we don't need to do anything.
3150e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
3151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
3152e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
3153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
3154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Since both black and grey have a 1 in the first position and white does
3158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // not have a 1 there we only need to check one bit.
3159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, &done, Label::kNear);
3161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
3163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for impossible bit pattern.
3164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label ok;
3165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    push(mask_scratch);
3166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // shl.  May overflow making the check conservative.
3167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    add(mask_scratch, mask_scratch);
3168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
3169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    j(zero, &ok, Label::kNear);
3170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int3();
3171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bind(&ok);
3172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    pop(mask_scratch);
3173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Value is white.  We check whether it is data that doesn't need scanning.
3176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Currently only checks for HeapNumber and non-cons strings.
3177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register map = ecx;  // Holds map while checking type.
3178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register length = ecx;  // Holds length of object after checking type.
3179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label not_heap_number;
3180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label is_data_object;
3181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for heap-number
3183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(map, FieldOperand(value, HeapObject::kMapOffset));
3184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(map, isolate()->factory()->heap_number_map());
3185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &not_heap_number, Label::kNear);
3186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(length, Immediate(HeapNumber::kSize));
3187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&is_data_object, Label::kNear);
3188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&not_heap_number);
3190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for strings.
3191e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
3192e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
3193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If it's a string and it's not a cons string then it's an object containing
3194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // no GC pointers.
3195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register instance_type = ecx;
3196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
3197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask);
3198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_zero, value_is_white_and_not_data);
3199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // It's a non-indirect (non-cons and non-slice) string.
3200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If it's external, the length is just ExternalString::kSize.
3201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
3202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label not_external;
3203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // External strings are the only ones with the kExternalStringTag bit
3204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // set.
3205e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, kSeqStringTag & kExternalStringTag);
3206e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, kConsStringTag & kExternalStringTag);
3207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  test_b(instance_type, kExternalStringTag);
3208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(zero, &not_external, Label::kNear);
3209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(length, Immediate(ExternalString::kSize));
3210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&is_data_object, Label::kNear);
3211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&not_external);
3213b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Sequential string, either Latin1 or UC16.
3214e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kOneByteStringTag == 0x04);
3215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(length, Immediate(kStringEncodingMask));
3216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  xor_(length, Immediate(kStringEncodingMask));
3217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(length, Immediate(0x04));
3218b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Value now either 4 (if Latin1) or 8 (if UC16), i.e., char-size shifted
3219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // by 2. If we multiply the string length as smi by this, it still
3220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // won't overflow a 32-bit value.
3221e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize);
3222e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(SeqOneByteString::kMaxSize <=
3223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
3224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  imul(length, FieldOperand(value, String::kLengthOffset));
3225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(length, 2 + kSmiTagSize + kSmiShiftSize);
3226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
3227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(length, Immediate(~kObjectAlignmentMask));
3228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&is_data_object);
3230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Value is a data object, and it is white.  Mark it black.  Since we know
3231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // that the object is white we can make it black by flipping one bit.
3232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
3233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
3235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
3236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      length);
3237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (emit_debug_code()) {
3238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
3239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
3240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Check(less_equal, kLiveBytesCountOverflowChunkSize);
3241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&done);
3244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::EnumLength(Register dst, Register map) {
3248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(dst, FieldOperand(map, Map::kBitField3Offset));
3250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  and_(dst, Immediate(Map::EnumLengthBits::kMask));
3251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiTag(dst);
3252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
3256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label next, start;
3257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, eax);
3258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the enum length field is properly initialized, indicating that
3260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // there is an enum cache.
3261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
3262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EnumLength(edx, ebx);
3264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
3265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, call_runtime);
3266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  jmp(&start);
3268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&next);
3270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
3271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // For all objects but the receiver, check that the cache is empty.
3273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EnumLength(edx, ebx);
3274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(edx, Immediate(Smi::FromInt(0)));
3275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, call_runtime);
3276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&start);
3278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that there are no elements. Register rcx contains the current JS
3280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object we've reached through the prototype chain.
3281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label no_elements;
3282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
3283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(ecx, isolate()->factory()->empty_fixed_array());
3284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, &no_elements);
3285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Second chance, the object may be using the empty slow element dictionary.
3287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
3288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, call_runtime);
3289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&no_elements);
3291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
3292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(ecx, isolate()->factory()->null_value());
3293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &next);
3294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TestJSArrayForAllocationMemento(
3298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register receiver_reg,
3299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch_reg,
3300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* no_memento_found) {
3301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference new_space_start =
3302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::new_space_start(isolate());
3303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference new_space_allocation_top =
3304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::new_space_allocation_top_address(isolate());
3305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  lea(scratch_reg, Operand(receiver_reg,
3307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
3308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch_reg, Immediate(new_space_start));
3309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(less, no_memento_found);
3310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
3311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(greater, no_memento_found);
3312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(MemOperand(scratch_reg, -AllocationMemento::kSize),
3313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate(isolate()->factory()->allocation_memento_map()));
3314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
3318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object,
3319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch0,
3320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register scratch1,
3321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* found) {
3322e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch1.is(scratch0));
3323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Factory* factory = isolate()->factory();
3324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register current = scratch0;
3325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label loop_again;
3326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // scratch contained elements pointer.
3328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(current, object);
3329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop based on the map going up the prototype chain.
3331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bind(&loop_again);
3332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(current, FieldOperand(current, HeapObject::kMapOffset));
3333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
3334d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  DecodeField<Map::ElementsKindBits>(scratch1);
3335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
3336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(equal, found);
3337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(current, FieldOperand(current, Map::kPrototypeOffset));
3338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  cmp(current, Immediate(factory->null_value()));
3339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  j(not_equal, &loop_again);
3340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
3344e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!dividend.is(eax));
3345e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!dividend.is(edx));
334642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  base::MagicNumbersForDivision<uint32_t> mag =
334742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
334842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  mov(eax, Immediate(mag.multiplier));
3349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  imul(dividend);
335042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
335142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  if (divisor > 0 && neg) add(edx, dividend);
335242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend);
335342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  if (mag.shift > 0) sar(edx, mag.shift);
3354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  mov(eax, dividend);
3355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  shr(eax, 31);
3356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  add(edx, eax);
3357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} }  // namespace v8::internal
3361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif  // V8_TARGET_ARCH_X87
3363