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_X64
8864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
96474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/call-optimization.h"
106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/handler-compiler.h"
116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@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
182b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
192b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, Label* miss_label, Register receiver,
202b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Handle<Name> name, Register scratch0, Register scratch1) {
21e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(name->IsUniqueName());
22e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!receiver.is(scratch0));
23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Counters* counters = masm->isolate()->counters();
24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->negative_lookups(), 1);
25864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->negative_lookups_miss(), 1);
26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kInterceptorOrAccessCheckNeededMask =
30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
31864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
32864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Bail out if the receiver has a named interceptor or requires access checks.
336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ testb(FieldOperand(scratch0, Map::kBitFieldOffset),
346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org           Immediate(kInterceptorOrAccessCheckNeededMask));
35864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, miss_label);
36864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
37864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that receiver is a JSObject.
38864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpInstanceType(scratch0, FIRST_SPEC_OBJECT_TYPE);
39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below, miss_label);
40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load properties array.
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register properties = scratch0;
436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the properties array is a dictionary.
466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                 Heap::kHashTableMapRootIndex);
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss_label);
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  NameDictionaryLookupStub::GenerateNegativeLookup(masm, miss_label, &done,
526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                                   properties, name, scratch1);
53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
54864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ DecrementCounter(counters->negative_lookups_miss(), 1);
55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
582b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
592b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, int index, Register prototype, Label* miss) {
606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Isolate* isolate = masm->isolate();
61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the global function with the given index.
62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSFunction> function(
636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      JSFunction::cast(isolate->native_context()->get(index)));
646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check we're still in the same context.
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = prototype;
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(scratch, Operand(rsi, offset));
696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Cmp(Operand(scratch, Context::SlotOffset(index)), function);
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss);
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load its initial map. The global functions all have initial maps.
746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(prototype, Handle<Map>(function->initial_map()));
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the prototype from the initial map.
766474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
802b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
816474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Register receiver, Register result, Register scratch,
826474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Label* miss_label) {
836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ TryGetFunctionPrototype(receiver, result, miss_label);
846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  if (!result.is(rax)) __ movp(rax, result);
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
88864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
896474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
906474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                     Register holder, Register name,
91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     Handle<JSObject> holder_obj) {
92f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
93f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
94f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
95f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
96f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(name);
98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
99e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
1006474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(kScratchRegister, interceptor);
1016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(kScratchRegister);
1026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver);
1036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(holder);
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic void CompileCallLoadPropertyWithInterceptor(
1086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Register receiver, Register holder, Register name,
1096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSObject> holder_obj, IC::UtilityId id) {
110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
111f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
112f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org                           NamedLoadHandlerCompiler::kInterceptorArgsLength);
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Generate call to api function.
1172b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateFastApiCall(
1182b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, const CallOptimization& optimization,
1192b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Handle<Map> receiver_map, Register receiver, Register scratch_in,
1202b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    bool is_store, int argc, Register* values) {
1216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(optimization.is_simple_api_call());
1226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
1236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(scratch_in);
124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // receiver
1256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver);
126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Write the arguments to stack frame.
127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < argc; i++) {
1286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Register arg = values[argc - 1 - i];
129e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!receiver.is(arg));
130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!scratch_in.is(arg));
1316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(arg);
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(scratch_in);
134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Stack now matches JSFunction abi.
135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Abi for CallApiFunctionStub.
1376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register callee = rax;
1386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register call_data = rbx;
1396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register holder = rcx;
1406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register api_function_address = rdx;
1416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Register scratch = rdi;  // scratch_in is no longer valid.
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put holder in place.
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallOptimization::HolderLookup holder_lookup;
1456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Handle<JSObject> api_holder =
1466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (holder_lookup) {
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderIsReceiver:
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Move(holder, receiver);
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderFound:
1526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Move(holder, api_holder);
1536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      break;
154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CallOptimization::kHolderNotFound:
155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Isolate* isolate = masm->isolate();
160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSFunction> function = optimization.constant_function();
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> call_data_obj(api_call_info->data(), isolate);
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put callee in place.
1656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(callee, function);
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool call_data_undefined = false;
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put call_data in place.
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (isolate->heap()->InNewSpace(*call_data_obj)) {
1706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Move(scratch, api_call_info);
1716474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (call_data_obj->IsUndefined()) {
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    call_data_undefined = true;
1746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1766474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Move(call_data, call_data_obj);
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put api_function_address in place.
180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address function_address = v8::ToCData<Address>(api_call_info->callback());
1816474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(api_function_address, function_address,
1826474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org          RelocInfo::EXTERNAL_REFERENCE);
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Jump to stub.
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallStub(&stub);
187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1902b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid PropertyHandlerCompiler::GenerateCheckPropertyCell(
1912b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
1922b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Register scratch, Label* miss) {
1936474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
194e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cell->value()->IsTheHole());
1956474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(scratch, cell);
1966474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Cmp(FieldOperand(scratch, Cell::kValueOffset),
1976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org         masm->isolate()->factory()->the_hole_value());
198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, miss);
199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter(
2036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
2046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSFunction> setter) {
2056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // ----------- S t a t e -------------
2066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  //  -- rsp[0] : return address
2076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // -----------------------------------
2086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  {
2096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Save value register, so we can restore it later.
2126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(value());
2136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    if (!setter.is_null()) {
2156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // Call the JavaScript setter with receiver and value on the stack.
2166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
2176474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        // Swap in the global receiver.
2186474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(receiver,
2196474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
2206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
2216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Push(receiver);
2226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Push(value());
2236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount actual(1);
2246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount expected(setter);
2256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
2266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                        NullCallWrapper());
2276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    } else {
2286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // If we generate a global code snippet for deoptimization only, remember
2296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // the place to continue after deoptimization.
2306474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
2316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    }
2326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // We have to return the passed value, not the return value of the setter.
2346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Pop(rax);
2356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Restore context register.
2376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  }
2396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ ret(0);
2406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter(
2446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
2456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    Handle<JSFunction> getter) {
2466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // ----------- S t a t e -------------
2476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  //  -- rax    : receiver
2486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  //  -- rcx    : name
2496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  //  -- rsp[0] : return address
2506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // -----------------------------------
2516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  {
2526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    if (!getter.is_null()) {
2556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // Call the JavaScript getter with the receiver on the stack.
2566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
2576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        // Swap in the global receiver.
2586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(receiver,
2596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
2606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
2616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Push(receiver);
2626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount actual(0);
2636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      ParameterCount expected(getter);
2646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
2656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                        NullCallWrapper());
2666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    } else {
2676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // If we generate a global code snippet for deoptimization only, remember
2686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      // the place to continue after deoptimization.
2696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
2706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    }
2716474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2726474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    // Restore context register.
2736474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  }
2756474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ ret(0);
2766474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2776474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2786474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2796474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgstatic void StoreIC_PushArgs(MacroAssembler* masm) {
2809aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register receiver = StoreDescriptor::ReceiverRegister();
2819aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register name = StoreDescriptor::NameRegister();
2829aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register value = StoreDescriptor::ValueRegister();
2836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value));
2856474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2866474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(rbx);
2876474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver);
2886474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(name);
2896474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(value);
2906474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(rbx);
2916474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
2926474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2936474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2946474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
2956474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Return address is on the stack.
2966474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  StoreIC_PushArgs(masm);
2976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
2986474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Do tail-call to runtime routine.
2996474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate());
3006474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ TailCallExternalReference(ref, 3, 1);
3016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}
3026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
3056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Return address is on the stack.
3066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  StoreIC_PushArgs(masm);
3076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
3086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Do tail-call to runtime routine.
3096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate());
3106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ TailCallExternalReference(ref, 3, 1);
3113e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org}
3123e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3133e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3143e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org#undef __
3156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#define __ ACCESS_MASM((masm()))
3163e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3173e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3183e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
3193e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                                                    Handle<Name> name) {
3203e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  if (!label->is_unused()) {
3213e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    __ bind(label);
3226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Move(this->name(), name);
3233e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  }
3243e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org}
3253e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
3263e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// store is successful.
3292b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreTransition(
3303e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<Map> transition, Handle<Name> name, Register receiver_reg,
3313e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Register storage_reg, Register value_reg, Register scratch1,
3323e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Register scratch2, Register unused, Label* miss_label, Label* slow) {
333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int descriptor = transition->LastAdded();
334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DescriptorArray* descriptors = transition->instance_descriptors();
335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PropertyDetails details = descriptors->GetDetails(descriptor);
336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation representation = details.representation();
337e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!representation.IsNone());
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == CONSTANT) {
3403e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
3416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Cmp(value_reg, constant);
342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, miss_label);
343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsSmi()) {
3446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsHeapObject()) {
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(value_reg, miss_label);
347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HeapType* field_type = descriptors->GetFieldType(descriptor);
348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HeapType::Iterator<Map> it = field_type->Classes();
349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!it.Done()) {
350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label do_store;
351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      while (true) {
352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CompareMap(value_reg, it.Current());
353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        it.Advance();
354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (it.Done()) {
355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ j(not_equal, miss_label);
356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, &do_store, Label::kNear);
359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&do_store);
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (representation.IsDouble()) {
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label do_store, heap_number;
3646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE);
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
3676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ SmiToInteger32(scratch1, value_reg);
3686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Cvtlsi2sd(xmm0, scratch1);
369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&do_store);
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&heap_number);
3723e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
3733e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                DONT_DO_SMI_CHECK);
3746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&do_store);
3776474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Stub never generated for objects that require access checks.
381e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!transition->is_access_check_needed());
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Perform map transition for the receiver if necessary.
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == FIELD &&
3857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The properties must be extended before we can store the value.
387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We jump to a runtime call that extends the properties array.
3886474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ PopReturnAddressTo(scratch1);
3896474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(receiver_reg);
3906474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(transition);
3916474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(value_reg);
3926474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ PushReturnAddressFrom(scratch1);
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ TailCallExternalReference(
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
3953e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org                          isolate()),
3963e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        3, 1);
397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the map of the object.
4016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(scratch1, transition);
4026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Update the write barrier for the map field.
4056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2,
4066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                      kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (details.type() == CONSTANT) {
4096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    DCHECK(value_reg.is(rax));
410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ ret(0);
411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int index = transition->instance_descriptors()->GetFieldIndex(
415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      transition->LastAdded());
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust for the number of properties stored in the object. Even in the
418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // face of a transition we can use the old map here because the size of the
419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object and the number of in-object properties is not going to change.
4207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  index -= transition->inobject_properties();
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(verwaest): Share this code as a code stub.
4236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  SmiCheck smi_check =
4246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (index < 0) {
426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Set the property straight into the object.
4277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int offset = transition->instance_size() + (index * kPointerSize);
428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (representation.IsDouble()) {
4296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(FieldOperand(receiver_reg, offset), storage_reg);
430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(FieldOperand(receiver_reg, offset), value_reg);
432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!representation.IsSmi()) {
435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the array address.
436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!representation.IsDouble()) {
4376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(storage_reg, value_reg);
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
4406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                          kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Write to the properties array.
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Get the properties array (optimistically).
4466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (representation.IsDouble()) {
4486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(FieldOperand(scratch1, offset), storage_reg);
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(FieldOperand(scratch1, offset), value_reg);
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!representation.IsSmi()) {
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the array address.
455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!representation.IsDouble()) {
4566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(storage_reg, value_reg);
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
4586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
4596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                          kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Return the value (register rax).
4646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(value_reg.is(rax));
465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
469a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
4709d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                                                   Register value_reg,
4719d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                                                   Label* miss_label) {
4729d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  DCHECK(lookup->representation().IsHeapObject());
4739d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  __ JumpIfSmi(value_reg, miss_label);
4749d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
4759d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  Label do_store;
4769d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  while (true) {
4779d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    __ CompareMap(value_reg, it.Current());
4789d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    it.Advance();
4799d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    if (it.Done()) {
4809d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org      __ j(not_equal, miss_label);
4819d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org      break;
482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4839d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    __ j(equal, &do_store, Label::kNear);
484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4858640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  __ bind(&do_store);
486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4879d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
4889d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org                      lookup->representation());
4899d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  GenerateTailCall(masm(), stub.GetCode());
490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4932b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgRegister PropertyHandlerCompiler::CheckPrototypes(
4947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register object_reg, Register holder_reg, Register scratch1,
4957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register scratch2, Handle<Name> name, Label* miss,
4967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    PrototypeCheckType check) {
4977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Make sure there's no overlap between holder and object registers.
500e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
5016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
5026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org         !scratch2.is(scratch1));
503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Keep track of the current object in register reg.  On the first
5056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // iteration, reg is an alias for object_reg, on later iterations,
5066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // it is an alias for holder_reg.
507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = object_reg;
508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int depth = 0;
509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSObject> current = Handle<JSObject>::null();
5116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  if (type()->IsConstant()) {
5127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    current = Handle<JSObject>::cast(type()->AsConstant()->Value());
5136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  }
514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSObject> prototype = Handle<JSObject>::null();
515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> current_map = receiver_map;
5167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Map> holder_map(holder()->map());
517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Traverse the prototype chain and check the maps in the prototype chain for
518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // fast and global objects or do negative lookup for normal objects.
519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  while (!current_map.is_identical_to(holder_map)) {
520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ++depth;
521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Only global objects and objects that do not require access
523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // checks are allowed in stubs.
524e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(current_map->IsJSGlobalProxyMap() ||
525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           !current_map->is_access_check_needed());
526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    prototype = handle(JSObject::cast(current_map->prototype()));
528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (current_map->is_dictionary_map() &&
5293e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        !current_map->IsJSGlobalObjectMap()) {
5303e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!name->IsUniqueName()) {
532e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(name->IsString());
533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        name = factory()->InternalizeString(Handle<String>::cast(name));
534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
535e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(current.is_null() ||
536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             current->property_dictionary()->FindEntry(name) ==
5376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                 NameDictionary::kNotFound);
538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
5406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                       scratch2);
541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg = holder_reg;  // From now on the object will be in holder_reg.
5446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      bool in_new_space = heap()->InNewSpace(*prototype);
547d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // Two possible reasons for loading the prototype from the map:
548d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // (1) Can't store references to new space in code.
549d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      // (2) Handler is shared for all receivers with the same prototype
550d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      //     map (but not necessarily the same prototype instance).
551d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      bool load_prototype_from_map = in_new_space || depth == 1;
5526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (load_prototype_from_map) {
5536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        // Save the map in scratch1 for later.
5546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
5556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (depth != 1 || check == CHECK_ALL_MAPS) {
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Check access rights to the global object.  This has to happen after
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // the map check so that we know that the object is actually a global
562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // object.
5633e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // This allows us to install generated handlers for accesses to the
5643e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // global proxy (as opposed to using slow ICs). See corresponding code
5653e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      // in LookupForRead().
566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (current_map->IsJSGlobalProxyMap()) {
5676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ CheckAccessGlobalProxy(reg, scratch2, miss);
568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (current_map->IsJSGlobalObjectMap()) {
5696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
5706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                                  name, scratch2, miss);
571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg = holder_reg;  // From now on the object will be in holder_reg.
573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
574d35a295c4172547d6718e2ae3816fadfaef0311dmachenbach@chromium.org      if (load_prototype_from_map) {
5756474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
5776474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ Move(reg, prototype);
578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Go to the next object in the prototype chain.
582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    current = prototype;
583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    current_map = handle(current->map());
584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Log the check depth.
587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (depth != 0 || check == CHECK_ALL_MAPS) {
590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check the holder map.
591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Perform security check for access to the global object.
595e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(current_map->IsJSGlobalProxyMap() ||
596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         !current_map->is_access_check_needed());
597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (current_map->IsJSGlobalProxyMap()) {
5986474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ CheckAccessGlobalProxy(reg, scratch1, miss);
599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the register containing the holder.
602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return reg;
603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6062b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!miss->is_unused()) {
608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label success;
609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&success);
610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(miss);
611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&success);
613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6172b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!miss->is_unused()) {
619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label success;
620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&success);
6213e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    GenerateRestoreName(miss, name);
622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&success);
624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6282b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadCallback(
6292b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org    Register reg, Handle<ExecutableAccessorInfo> callback) {
630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Insert additional parameters into the stack frame above return address.
6316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!scratch4().is(reg));
6326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(scratch4());
633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
6406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
6416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver());  // receiver
6426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  if (heap()->InNewSpace(callback->data())) {
643e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!scratch2().is(reg));
6446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Move(scratch2(), callback);
6456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(FieldOperand(scratch2(),
6466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org                         ExecutableAccessorInfo::kDataOffset));  // data
647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
6486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(Handle<Object>(callback->data(), isolate()));
649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
6506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  DCHECK(!kScratchRegister.is(reg));
6516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
6526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(kScratchRegister);  // return value
6536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(kScratchRegister);  // return value default
6546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushAddress(ExternalReference::isolate_address(isolate()));
6556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(reg);     // holder
6566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(name());  // name
6576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Save a pointer to where we pushed the arguments pointer.  This will be
658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // passed as the const PropertyAccessorInfo& to the C++ callback.
659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(scratch4());
661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Abi for CallApiGetter
6636313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  Register api_function_address = ApiGetterDescriptor::function_address();
6646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  Address getter_address = v8::ToCData<Address>(callback->getter());
6656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE);
666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallApiGetterStub stub(isolate());
668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallStub(&stub);
669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6722b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the constant value.
6746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(rax, value);
675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6795e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
6805e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    LookupIterator* it, Register holder_reg) {
681e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(holder()->HasNamedInterceptor());
682e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6845e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Compile the interceptor call, followed by inline code to load the
6855e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // property from further up the prototype chain if the call fails.
6865e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Check that the maps haven't changed.
6875e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
6885e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
6895e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Preserve the receiver register explicitly whenever it is different from the
6905e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // holder and it is needed should the interceptor return without any result.
6915e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
6925e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // case might cause a miss during the prototype check.
6935e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  bool must_perform_prototype_check =
6945e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      !holder().is_identical_to(it->GetHolder<JSObject>());
6955e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  bool must_preserve_receiver_reg =
6965e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      !receiver().is(holder_reg) &&
6971af4d9551ad496a28c342004b1a4e2a3840228f7machenbach@chromium.org      (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check);
6985e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
6995e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Save necessary data before invoking an interceptor.
7005e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // Requires a frame to make GC aware of pushed pointers.
7015e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  {
7025e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    FrameScope frame_scope(masm(), StackFrame::INTERNAL);
7035e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7045e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    if (must_preserve_receiver_reg) {
7056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Push(receiver());
706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
7076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(holder_reg);
7086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Push(this->name());
7095e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7105e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Invoke an interceptor.  Note: map checks from receiver to
7115e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // interceptor's holder has been compiled before (see a caller
7125e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // of this method.)
7135e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    CompileCallLoadPropertyWithInterceptor(
7145e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        masm(), receiver(), holder_reg, this->name(), holder(),
7155e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        IC::kLoadPropertyWithInterceptorOnly);
7165e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7175e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Check if interceptor provided a value for property.  If it's
7185e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // the case, return immediately.
7195e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    Label interceptor_failed;
7206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
7215e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ j(equal, &interceptor_failed);
7225e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    frame_scope.GenerateLeaveFrame();
7235e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ ret(0);
724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7255e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    __ bind(&interceptor_failed);
7266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Pop(this->name());
7276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ Pop(holder_reg);
7285e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    if (must_preserve_receiver_reg) {
7296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ Pop(receiver());
730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7325e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    // Leave the internal frame.
733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
7345e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7355e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  GenerateLoadPostInterceptor(it, holder_reg);
7365e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
7375e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7385e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7395e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
7406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  // Call the runtime system to load the interceptor.
7415e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(holder()->HasNamedInterceptor());
7425e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
7436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(scratch2());
7445e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
7455e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org                           holder());
7466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(scratch2());
7475e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
7485e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  ExternalReference ref = ExternalReference(
7495e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
7505e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  __ TailCallExternalReference(
7515e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7552b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
7567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<JSObject> object, Handle<Name> name,
757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<ExecutableAccessorInfo> callback) {
7587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Register holder_reg = Frontend(receiver(), name);
759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(scratch1());
7616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver());
7626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(holder_reg);
7636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(callback);  // callback info
764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Push(name);
7656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(value());
7666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(scratch1());
767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do tail-call to the runtime system.
769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference store_callback_property =
770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallExternalReference(store_callback_property, 5, 1);
772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
7782b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
7797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Name> name) {
7806474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PopReturnAddressTo(scratch1());
7816474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(receiver());
7826474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(this->name());
7836474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Push(value());
7846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ PushReturnAddressFrom(scratch1());
785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do tail-call to the runtime system.
787f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org  ExternalReference store_ic_property = ExternalReference(
788f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org      IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TailCallExternalReference(store_ic_property, 3, 1);
790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
796fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgRegister NamedStoreHandlerCompiler::value() {
7979aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  return StoreDescriptor::ValueRegister();
798fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org}
7992b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org
8002b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org
8012b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.orgHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
8023e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label miss;
8047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  FrontendHeader(receiver(), name, &miss);
8056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the value from the cell.
8079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register result = StoreDescriptor::ValueRegister();
8086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ Move(result, cell);
8096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  __ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for deleted property if property can actually be deleted.
812e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (is_configurable) {
8136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &miss);
815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (FLAG_debug_code) {
8166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Counters* counters = isolate()->counters();
821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IncrementCounter(counters->named_load_global_stub(), 1);
822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ret(0);
823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
8242b995c4171e67960088466af11110c6f6aeea4fcmachenbach@chromium.org  FrontendFooter(name, &miss);
825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Return the generated code.
827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GetCode(kind(), Code::NORMAL, name);
828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __
832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
8336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org}  // namespace v8::internal
834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
8356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#endif  // V8_TARGET_ARCH_X64
836