16474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org// Copyright 2014 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
76474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#if V8_TARGET_ARCH_IA32
8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
96474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/call-optimization.h"
106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/handler-compiler.h"
11d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org#include "src/ic/ic.h"
12864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
13864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 {
14864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal {
15864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
16864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define __ ACCESS_MASM(masm)
17864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
18864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
196474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter(
206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSFunction> getter) {
226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  {
236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    if (!getter.is_null()) {
266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // Call the JavaScript getter with the receiver on the stack.
276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        // Swap in the global receiver.
296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov(receiver,
306474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org               FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ push(receiver);
336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount actual(0);
346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount expected(getter);
356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                        NullCallWrapper());
376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    } else {
386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // If we generate a global code snippet for deoptimization only, remember
396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // the place to continue after deoptimization.
406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    }
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Restore context register.
446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ ret(0);
47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
502b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
512b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, Label* miss_label, Register receiver,
522b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Handle<Name> name, Register scratch0, Register scratch1) {
53e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(name->IsUniqueName());
54e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!receiver.is(scratch0));
55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Counters* counters = masm->isolate()->counters();
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->negative_lookups(), 1);
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->negative_lookups_miss(), 1);
58864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
60864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kInterceptorOrAccessCheckNeededMask =
62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
63864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
64864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Bail out if the receiver has a named interceptor or requires access checks.
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test_b(FieldOperand(scratch0, Map::kBitFieldOffset),
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            kInterceptorOrAccessCheckNeededMask);
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, miss_label);
68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
69864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that receiver is a JSObject.
70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpInstanceType(scratch0, FIRST_SPEC_OBJECT_TYPE);
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below, miss_label);
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load properties array.
74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register properties = scratch0;
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
76864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the properties array is a dictionary.
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(masm->isolate()->factory()->hash_table_map()));
80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss_label);
81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  NameDictionaryLookupStub::GenerateNegativeLookup(masm, miss_label, &done,
846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                                   properties, name, scratch1);
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ DecrementCounter(counters->negative_lookups_miss(), 1);
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
88864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
89864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
902b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
912b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, int index, Register prototype, Label* miss) {
92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the global function with the given index.
93864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSFunction> function(
94864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      JSFunction::cast(masm->isolate()->native_context()->get(index)));
95864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check we're still in the same context.
96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = prototype;
97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, Operand(esi, offset));
99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(scratch, Context::SlotOffset(index)), function);
101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss);
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load its initial map. The global functions all have initial maps.
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(prototype, Immediate(Handle<Map>(function->initial_map())));
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the prototype from the initial map.
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1102b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
1112b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, Register receiver, Register scratch1,
1122b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Register scratch2, Label* miss_label) {
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, scratch1);
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Generate call to api function.
120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// This function uses push() to generate smaller, faster code than
121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the version above. It is an optimization that should will be removed
122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// when api call ICs are generated in hydrogen.
1232b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateFastApiCall(
1242b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, const CallOptimization& optimization,
1252b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Handle<Map> receiver_map, Register receiver, Register scratch_in,
1262b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    bool is_store, int argc, Register* values) {
127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy return value.
128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(scratch_in);
129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // receiver
130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(receiver);
131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Write the arguments to stack frame.
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < argc; i++) {
1336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Register arg = values[argc - 1 - i];
134e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!receiver.is(arg));
135e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!scratch_in.is(arg));
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(arg);
137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(scratch_in);
139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Stack now matches JSFunction abi.
140e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(optimization.is_simple_api_call());
141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Abi for CallApiFunctionStub.
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register callee = eax;
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register call_data = ebx;
145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register holder = ecx;
146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register api_function_address = edx;
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = edi;  // scratch_in is no longer valid.
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put holder in place.
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallOptimization::HolderLookup holder_lookup;
1516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Handle<JSObject> api_holder =
1526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (holder_lookup) {
154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderIsReceiver:
155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Move(holder, receiver);
156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderFound:
158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ LoadHeapObject(holder, api_holder);
1596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      break;
160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderNotFound:
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Isolate* isolate = masm->isolate();
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSFunction> function = optimization.constant_function();
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> call_data_obj(api_call_info->data(), isolate);
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put callee in place.
171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadHeapObject(callee, function);
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool call_data_undefined = false;
174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put call_data in place.
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate->heap()->InNewSpace(*call_data_obj)) {
176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(scratch, api_call_info);
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (call_data_obj->IsUndefined()) {
179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    call_data_undefined = true;
180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(call_data, Immediate(isolate->factory()->undefined_value()));
181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(call_data, call_data_obj);
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put api_function_address in place.
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address function_address = v8::ToCData<Address>(api_call_info->callback());
187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(api_function_address, Immediate(function_address));
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Jump to stub.
190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallStub(&stub);
192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Generate code to check that a global property cell is empty. Create
196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the property cell at compilation time if no cell exists for the
197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// property.
1982b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateCheckPropertyCell(
1992b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
2002b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Register scratch, Label* miss) {
2016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
202e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cell->value()->IsTheHole());
203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (masm->serializer_enabled()) {
205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(scratch, Immediate(cell));
206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset),
207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(the_hole));
208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(Operand::ForCell(cell), Immediate(the_hole));
210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss);
212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter(
2166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
2176474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSFunction> setter) {
2186474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // ----------- S t a t e -------------
2196474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  //  -- esp[0] : return address
2206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // -----------------------------------
2216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  {
2226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Save value register, so we can restore it later.
2256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ push(value());
2266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    if (!setter.is_null()) {
2286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // Call the JavaScript setter with receiver and value on the stack.
2296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
2306474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        // Swap in the global receiver.
2316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov(receiver,
2326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org               FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
2336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
2346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ push(receiver);
2356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ push(value());
2366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount actual(1);
2376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount expected(setter);
2386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
2396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                        NullCallWrapper());
2406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    } else {
2416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // If we generate a global code snippet for deoptimization only, remember
2426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // the place to continue after deoptimization.
2436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
2446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    }
2456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // We have to return the passed value, not the return value of the setter.
2476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ pop(eax);
2486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Restore context register.
2506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  }
2526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ ret(0);
2536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
2576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                     Register holder, Register name,
2586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                     Handle<JSObject> holder_obj) {
2596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
2606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
2616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
2626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
2636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
2646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(name);
2656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
2666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
2676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register scratch = name;
2686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ mov(scratch, Immediate(interceptor));
2696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(scratch);
2706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(receiver);
2716474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(holder);
2726474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2736474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2756474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgstatic void CompileCallLoadPropertyWithInterceptor(
2766474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Register receiver, Register holder, Register name,
2776474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSObject> holder_obj, IC::UtilityId id) {
2786474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
2796474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
2806474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                           NamedLoadHandlerCompiler::kInterceptorArgsLength);
2816474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2826474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgstatic void StoreIC_PushArgs(MacroAssembler* masm) {
2859aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register receiver = StoreDescriptor::ReceiverRegister();
2869aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register name = StoreDescriptor::NameRegister();
2879aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register value = StoreDescriptor::ValueRegister();
2886474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2896474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value));
2906474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2916474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ pop(ebx);
2926474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(receiver);
2936474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(name);
2946474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(value);
2956474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ push(ebx);
2966474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2986474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2996474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
3006474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Return address is on the stack.
3016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  StoreIC_PushArgs(masm);
3026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Do tail-call to runtime routine.
3046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate());
3056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ TailCallExternalReference(ref, 3, 1);
3066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
3076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
3106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Return address is on the stack.
3116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  StoreIC_PushArgs(masm);
3126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Do tail-call to runtime routine.
3146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate());
3156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ TailCallExternalReference(ref, 3, 1);
3163e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org}
3173e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3183e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3193e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org#undef __
3203e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org#define __ ACCESS_MASM(masm())
3213e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3223e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3233e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
3243e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                                                    Handle<Name> name) {
3253e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (!label->is_unused()) {
3263e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    __ bind(label);
3273e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    __ mov(this->name(), Immediate(name));
3283e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  }
3293e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org}
3303e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3313e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// store is successful.
3342b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreTransition(
3353e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<Map> transition, Handle<Name> name, Register receiver_reg,
3363e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Register storage_reg, Register value_reg, Register scratch1,
3373e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Register scratch2, Register unused, Label* miss_label, Label* slow) {
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int descriptor = transition->LastAdded();
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DescriptorArray* descriptors = transition->instance_descriptors();
340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PropertyDetails details = descriptors->GetDetails(descriptor);
341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation representation = details.representation();
342e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!representation.IsNone());
343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == CONSTANT) {
3453e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObject(value_reg, constant);
347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, miss_label);
348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsSmi()) {
3496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsHeapObject()) {
351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(value_reg, miss_label);
352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HeapType* field_type = descriptors->GetFieldType(descriptor);
353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HeapType::Iterator<Map> it = field_type->Classes();
354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!it.Done()) {
355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label do_store;
356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      while (true) {
357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CompareMap(value_reg, it.Current());
358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        it.Advance();
359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (it.Done()) {
360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ j(not_equal, miss_label);
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, &do_store, Label::kNear);
364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&do_store);
366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsDouble()) {
368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label do_store, heap_number;
36958a725587734a6889c689668fd01f0157ed749a6machenbach@chromium.org    __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE);
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(value_reg);
3736474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Cvtsi2sd(xmm0, value_reg);
374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiTag(value_reg);
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&do_store);
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&heap_number);
3783e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
3793e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                DONT_DO_SMI_CHECK);
3806474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&do_store);
3836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Stub never generated for objects that require access checks.
387e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!transition->is_access_check_needed());
388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Perform map transition for the receiver if necessary.
390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == FIELD &&
3917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The properties must be extended before we can store the value.
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We jump to a runtime call that extends the properties array.
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(scratch1);  // Return address.
395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(receiver_reg);
396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(transition));
397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(value_reg);
398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(scratch1);
399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ TailCallExternalReference(
400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
4013e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                          isolate()),
4023e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        3, 1);
403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the map of the object.
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch1, Immediate(transition));
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the write barrier for the map field.
4116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2,
4126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                      kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == CONSTANT) {
415e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(value_reg.is(eax));
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ ret(0);
417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int index = transition->instance_descriptors()->GetFieldIndex(
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      transition->LastAdded());
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust for the number of properties stored in the object. Even in the
424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // face of a transition we can use the old map here because the size of the
425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object and the number of in-object properties is not going to change.
4267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  index -= transition->inobject_properties();
427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  SmiCheck smi_check =
4296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(verwaest): Share this code as a code stub.
431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (index < 0) {
432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Set the property straight into the object.
4337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int offset = transition->instance_size() + (index * kPointerSize);
434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (representation.IsDouble()) {
435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(receiver_reg, offset), storage_reg);
436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(receiver_reg, offset), value_reg);
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!representation.IsSmi()) {
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the array address.
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!representation.IsDouble()) {
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(storage_reg, value_reg);
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
4466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                          kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Write to the properties array.
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Get the properties array (optimistically).
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (representation.IsDouble()) {
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(scratch1, offset), storage_reg);
455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(scratch1, offset), value_reg);
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!representation.IsSmi()) {
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the array address.
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!representation.IsDouble()) {
462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(storage_reg, value_reg);
463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
4656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                          kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the value (register eax).
470e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value_reg.is(eax));
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
475a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
4769d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                                                   Register value_reg,
4779d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                                                   Label* miss_label) {
4789d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  DCHECK(lookup->representation().IsHeapObject());
4799d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  __ JumpIfSmi(value_reg, miss_label);
4809d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
4819d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  Label do_store;
4829d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  while (true) {
4839d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    __ CompareMap(value_reg, it.Current());
4849d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    it.Advance();
4859d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    if (it.Done()) {
4869d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org      __ j(not_equal, miss_label);
4879d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org      break;
488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4899d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    __ j(equal, &do_store, Label::kNear);
490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4918640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  __ bind(&do_store);
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4939d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
4949d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                      lookup->representation());
4959d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  GenerateTailCall(masm(), stub.GetCode());
496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4992b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgRegister PropertyHandlerCompiler::CheckPrototypes(
5007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register object_reg, Register holder_reg, Register scratch1,
5017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register scratch2, Handle<Name> name, Label* miss,
5027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    PrototypeCheckType check) {
5037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Make sure there's no overlap between holder and object registers.
506e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
5076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
5086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org         !scratch2.is(scratch1));
509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Keep track of the current object in register reg.
511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = object_reg;
512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int depth = 0;
513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSObject> current = Handle<JSObject>::null();
5157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (type()->IsConstant())
5167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    current = Handle<JSObject>::cast(type()->AsConstant()->Value());
517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSObject> prototype = Handle<JSObject>::null();
518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> current_map = receiver_map;
5197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Map> holder_map(holder()->map());
520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Traverse the prototype chain and check the maps in the prototype chain for
521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // fast and global objects or do negative lookup for normal objects.
522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  while (!current_map.is_identical_to(holder_map)) {
523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ++depth;
524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Only global objects and objects that do not require access
526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // checks are allowed in stubs.
527e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(current_map->IsJSGlobalProxyMap() ||
528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           !current_map->is_access_check_needed());
529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    prototype = handle(JSObject::cast(current_map->prototype()));
531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (current_map->is_dictionary_map() &&
5323e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        !current_map->IsJSGlobalObjectMap()) {
5333e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!name->IsUniqueName()) {
535e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(name->IsString());
536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        name = factory()->InternalizeString(Handle<String>::cast(name));
537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
538e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(current.is_null() ||
539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             current->property_dictionary()->FindEntry(name) ==
5406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                 NameDictionary::kNotFound);
541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
5436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                       scratch2);
544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg = holder_reg;  // From now on the object will be in holder_reg.
547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      bool in_new_space = heap()->InNewSpace(*prototype);
550d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // Two possible reasons for loading the prototype from the map:
551d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // (1) Can't store references to new space in code.
552d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // (2) Handler is shared for all receivers with the same prototype
553d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      //     map (but not necessarily the same prototype instance).
554d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      bool load_prototype_from_map = in_new_space || depth == 1;
555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (depth != 1 || check == CHECK_ALL_MAPS) {
556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Check access rights to the global object.  This has to happen after
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // the map check so that we know that the object is actually a global
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // object.
5623e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // This allows us to install generated handlers for accesses to the
5633e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // global proxy (as opposed to using slow ICs). See corresponding code
5643e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // in LookupForRead().
565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (current_map->IsJSGlobalProxyMap()) {
566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (current_map->IsJSGlobalObjectMap()) {
5686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
5696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                  name, scratch2, miss);
570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
572d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      if (load_prototype_from_map) {
573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Save the map in scratch1 for later.
574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg = holder_reg;  // From now on the object will be in holder_reg.
578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
579d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      if (load_prototype_from_map) {
580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(reg, prototype);
583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Go to the next object in the prototype chain.
587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    current = prototype;
588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    current_map = handle(current->map());
589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Log the check depth.
592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (depth != 0 || check == CHECK_ALL_MAPS) {
595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check the holder map.
596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Perform security check for access to the global object.
600e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(current_map->IsJSGlobalProxyMap() ||
601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         !current_map->is_access_check_needed());
602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (current_map->IsJSGlobalProxyMap()) {
603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the register containing the holder.
607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return reg;
608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6112b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!miss->is_unused()) {
613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label success;
614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&success);
615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(miss);
616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&success);
618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6222b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!miss->is_unused()) {
624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label success;
625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&success);
6263e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    GenerateRestoreName(miss, name);
627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&success);
629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6332b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadCallback(
6342b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Register reg, Handle<ExecutableAccessorInfo> callback) {
635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Insert additional parameters into the stack frame above return address.
636e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch3().is(reg));
637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(scratch3());  // Get return address to place it below.
638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(receiver());  // receiver
646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push data from ExecutableAccessorInfo.
647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate()->heap()->InNewSpace(callback->data())) {
648e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!scratch2().is(reg));
649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(scratch2(), Immediate(callback));
650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset));
651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(Handle<Object>(callback->data(), isolate())));
653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(isolate()->factory()->undefined_value()));  // ReturnValue
655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ReturnValue default value
656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(isolate()->factory()->undefined_value()));
657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(reinterpret_cast<int>(isolate())));
658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(reg);  // holder
659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save a pointer to where we pushed the arguments. This will be
661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // passed as the const PropertyAccessorInfo& to the C++ callback.
662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(esp);
663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(name());  // name
665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(scratch3());  // Restore return address.
667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Abi for CallApiGetter
6696313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  Register getter_address = ApiGetterDescriptor::function_address();
670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address function_address = v8::ToCData<Address>(callback->getter());
671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(getter_address, Immediate(function_address));
672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallApiGetterStub stub(isolate());
674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallStub(&stub);
675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6782b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the constant value.
680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadObject(eax, value);
681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6855e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
6865e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    LookupIterator* it, Register holder_reg) {
687e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(holder()->HasNamedInterceptor());
688e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6905e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Compile the interceptor call, followed by inline code to load the
6915e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // property from further up the prototype chain if the call fails.
6925e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Check that the maps haven't changed.
6935e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
6945e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
6955e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Preserve the receiver register explicitly whenever it is different from the
6965e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // holder and it is needed should the interceptor return without any result.
6975e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
6985e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // case might cause a miss during the prototype check.
6995e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  bool must_perform_prototype_check =
7005e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      !holder().is_identical_to(it->GetHolder<JSObject>());
7015e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  bool must_preserve_receiver_reg =
7025e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      !receiver().is(holder_reg) &&
7031af4d9551ad496a28c342004b1a4e2a3840228f7machenbach@chromium.org      (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check);
7045e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7055e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Save necessary data before invoking an interceptor.
7065e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Requires a frame to make GC aware of pushed pointers.
7075e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  {
7085e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    FrameScope frame_scope(masm(), StackFrame::INTERNAL);
7095e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7105e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    if (must_preserve_receiver_reg) {
7115e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      __ push(receiver());
712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
7135e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ push(holder_reg);
7145e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ push(this->name());
7155e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7165e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Invoke an interceptor.  Note: map checks from receiver to
7175e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // interceptor's holder has been compiled before (see a caller
7185e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // of this method.)
7195e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    CompileCallLoadPropertyWithInterceptor(
7205e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        masm(), receiver(), holder_reg, this->name(), holder(),
7215e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        IC::kLoadPropertyWithInterceptorOnly);
7225e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7235e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Check if interceptor provided a value for property.  If it's
7245e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // the case, return immediately.
7255e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    Label interceptor_failed;
7265e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ cmp(eax, factory()->no_interceptor_result_sentinel());
7275e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ j(equal, &interceptor_failed);
7285e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    frame_scope.GenerateLeaveFrame();
7295e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ ret(0);
730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7315e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Clobber registers when generating debug-code to provoke errors.
7325e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ bind(&interceptor_failed);
7335e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    if (FLAG_debug_code) {
734e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      __ mov(receiver(), Immediate(bit_cast<int32_t>(kZapValue)));
735e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      __ mov(holder_reg, Immediate(bit_cast<int32_t>(kZapValue)));
736e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      __ mov(this->name(), Immediate(bit_cast<int32_t>(kZapValue)));
7375e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    }
738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7395e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ pop(this->name());
7405e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ pop(holder_reg);
7415e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    if (must_preserve_receiver_reg) {
7425e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      __ pop(receiver());
743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7455e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Leave the internal frame.
746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
7475e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7485e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  GenerateLoadPostInterceptor(it, holder_reg);
7495e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
7505e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7515e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7525e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
7535e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(holder()->HasNamedInterceptor());
7545e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
7555e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Call the runtime system to load the interceptor.
7565e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  __ pop(scratch2());  // save old return address
7575e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
7585e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                           holder());
7595e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  __ push(scratch2());  // restore old return address
7605e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7615e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  ExternalReference ref = ExternalReference(
7625e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
7635e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  __ TailCallExternalReference(
7645e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7682b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
7697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<JSObject> object, Handle<Name> name,
770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<ExecutableAccessorInfo> callback) {
7717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Register holder_reg = Frontend(receiver(), name);
772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(scratch1());  // remove the return address
774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(receiver());
775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(holder_reg);
776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(callback);
777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(name);
778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(value());
779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(scratch1());  // restore return address
780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do tail-call to the runtime system.
782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference store_callback_property =
783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallExternalReference(store_callback_property, 5, 1);
785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7912b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
7927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Name> name) {
793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(scratch1());  // remove the return address
794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(receiver());
795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(this->name());
796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(value());
797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(scratch1());  // restore return address
798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do tail-call to the runtime system.
800f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  ExternalReference store_ic_property = ExternalReference(
801f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org      IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallExternalReference(store_ic_property, 3, 1);
803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
809fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgRegister NamedStoreHandlerCompiler::value() {
8109aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  return StoreDescriptor::ValueRegister();
811fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org}
8122b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org
8132b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org
8142b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
8153e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label miss;
817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
8187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  FrontendHeader(receiver(), name, &miss);
819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the value from the cell.
8209aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register result = StoreDescriptor::ValueRegister();
821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (masm()->serializer_enabled()) {
8227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(result, Immediate(cell));
8237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(result, FieldOperand(result, PropertyCell::kValueOffset));
824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
8257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(result, Operand::ForCell(cell));
826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for deleted property if property can actually be deleted.
829e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (is_configurable) {
8307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ cmp(result, factory()->the_hole_value());
831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &miss);
832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (FLAG_debug_code) {
8337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ cmp(result, factory()->the_hole_value());
834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Counters* counters = isolate()->counters();
838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->named_load_global_stub(), 1);
839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The code above already loads the result into the return register.
840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
8422b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  FrontendFooter(name, &miss);
843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::NORMAL, name);
846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __
850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
8516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}  // namespace v8::internal
852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
8536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#endif  // V8_TARGET_ARCH_IA32
854