105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
45c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
65c838251403b0be9a882540f1922577abba4c872ager@chromium.org
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
89dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/ic-inl.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/stub-cache.h"
125c838251403b0be9a882540f1922577abba4c872ager@chromium.org
135c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
145c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
165c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define __ ACCESS_MASM(masm)
175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void ProbeTable(Isolate* isolate,
20c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       MacroAssembler* masm,
21c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Code::Flags flags,
22c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       StubCache::Table table,
2335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register receiver,
24c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register name,
2535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       // Number of the cache entry, not scaled.
26c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register offset,
27c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register scratch,
2835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register scratch2,
2935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register offset_scratch) {
30c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
31c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
3235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
33c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
34c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
35c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
3635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
37c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
38c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check the relative positions of the address fields.
39c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(value_off_addr > key_off_addr);
40c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
41c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
4235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(map_off_addr > key_off_addr);
4335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT((map_off_addr - key_off_addr) % 4 == 0);
4435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT((map_off_addr - key_off_addr) < (256 * 4));
45c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
46c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
4735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register base_addr = scratch;
4835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  scratch = no_reg;
4935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
5035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Multiply by 3 because there are 3 fields per entry (name, code, map).
5135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ sll(offset_scratch, offset, 1);
5235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(offset_scratch, offset_scratch, offset);
5335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
5435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Calculate the base address of the entry.
5535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ li(base_addr, Operand(key_offset));
5635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ sll(at, offset_scratch, kPointerSizeLog2);
5735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(base_addr, base_addr, at);
58c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
59c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the key in the entry matches the name.
6035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, MemOperand(base_addr, 0));
6135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, name, Operand(at));
6235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
6335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Check the map matches.
6435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr));
6535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
6635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, at, Operand(scratch2));
67c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
68c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the code entry from the cache.
6935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register code = scratch2;
7035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  scratch2 = no_reg;
7135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr));
72c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
73c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the flags match what we're looking for.
7435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register flags_reg = base_addr;
7535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  base_addr = no_reg;
7635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
7735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup));
7835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, flags_reg, Operand(flags));
7935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
8035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org#ifdef DEBUG
8135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
8235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org      __ jmp(&miss);
8335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
8435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org      __ jmp(&miss);
8535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    }
8635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org#endif
87c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
88c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Jump to the first instruction in the code stub.
8935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
9035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Jump(at);
91c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
92c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Miss: fall through.
93c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
94c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
95c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
96c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
97057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm,
98057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Label* miss_label,
99057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register receiver,
100057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Handle<Name> name,
101057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch0,
102057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch1) {
1039faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  ASSERT(name->IsUniqueName());
104057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  ASSERT(!receiver.is(scratch0));
105394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Counters* counters = masm->isolate()->counters();
106394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
107394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
108394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
109394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label done;
110394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
111394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  const int kInterceptorOrAccessCheckNeededMask =
112394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
113394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
114394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Bail out if the receiver has a named interceptor or requires access checks.
115394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register map = scratch1;
116394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
117394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
118394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
119394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, ne, scratch0, Operand(zero_reg));
120394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
121394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that receiver is a JSObject.
122394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
123394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
124394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
125394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Load properties array.
126394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register properties = scratch0;
127394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
128394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that the properties array is a dictionary.
129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
130394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register tmp = properties;
131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
132394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, ne, map, Operand(tmp));
133394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
134394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Restore the temporarily used register.
135394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
136394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
137394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1389faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
1399faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   miss_label,
1409faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   &done,
1419faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   receiver,
1429faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   properties,
1439faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   name,
1449faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   scratch1);
145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&done);
146394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
147394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
148394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
149394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1505c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCache::GenerateProbe(MacroAssembler* masm,
1515c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Code::Flags flags,
1525c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register receiver,
1535c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register name,
1545c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register scratch,
155e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org                              Register extra,
15635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                              Register extra2,
15735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                              Register extra3) {
158c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Isolate* isolate = masm->isolate();
159c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
160c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
16135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Make sure that code is valid. The multiplying code relies on the
16235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // entry size being 12.
16335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(sizeof(Entry) == 12);
164c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
165c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Make sure the flags does not name a specific type.
166c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
167c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
168c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Make sure that there are no register conflicts.
169c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(receiver));
170c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(name));
171c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(receiver));
172c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(name));
173c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(scratch));
174c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(receiver));
175c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(name));
176c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(scratch));
177c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(extra));
178c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
17935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Check register validity.
180c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(no_reg));
181c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(no_reg));
182c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(no_reg));
18335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(!extra3.is(no_reg));
18435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
18535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
18635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
18735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                      extra2, extra3);
188c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
189c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
19035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ JumpIfSmi(receiver, &miss);
191c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
192c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the map of the receiver and compute the hash.
1939faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(scratch, FieldMemOperand(name, Name::kHashFieldOffset));
19435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset));
19535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(scratch, scratch, at);
19635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t mask = kPrimaryTableSize - 1;
19735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // We shift out the last two bits because they are not part of the hash and
19835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // they are always 01 for maps.
19935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ srl(scratch, scratch, kHeapObjectTagSize);
20035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Xor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
20135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(scratch, scratch, Operand(mask));
202c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
203c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Probe the primary table.
20435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ProbeTable(isolate,
20535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             masm,
20635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             flags,
20735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             kPrimary,
20835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             receiver,
20935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             name,
21035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             scratch,
21135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra,
21235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra2,
21335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra3);
214c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
215c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Primary miss: Compute hash for secondary probe.
21635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ srl(at, name, kHeapObjectTagSize);
21735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Subu(scratch, scratch, at);
21835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t mask2 = kSecondaryTableSize - 1;
21935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
22035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(scratch, scratch, Operand(mask2));
221c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
222c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Probe the secondary table.
22335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ProbeTable(isolate,
22435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             masm,
22535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             flags,
22635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             kSecondary,
22735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             receiver,
22835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             name,
22935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             scratch,
23035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra,
23135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra2,
23235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra3);
233c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
234c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Cache miss: Fall-through and let caller handle the miss by
235c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // entering the runtime system.
236c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
23735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
23835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                      extra2, extra3);
2395c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2425c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
2435c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                       int index,
2445c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                       Register prototype) {
245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the global or builtins object from the current context.
246c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype,
24746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
24846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context from the global or builtins object.
24946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ lw(prototype,
25046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         FieldMemOperand(prototype, GlobalObject::kNativeContextOffset));
25146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the function from the native context.
252c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index)));
253c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the initial map.  The global functions all have initial maps.
254c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype,
255c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
256c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the prototype from the initial map.
257c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
2585c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
262c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
263c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    int index,
264c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register prototype,
265c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Label* miss) {
266c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Isolate* isolate = masm->isolate();
267c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the global function with the given index.
268c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function(
26946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      JSFunction::cast(isolate->native_context()->get(index)));
27057a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org
27157a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  // Check we're still in the same context.
27257a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  Register scratch = prototype;
27357a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
27457a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ lw(scratch, MemOperand(cp, offset));
27557a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
27657a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ lw(scratch, MemOperand(scratch, Context::SlotOffset(index)));
27757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ li(at, function);
27857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ Branch(miss, ne, at, Operand(scratch));
27957a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org
280c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load its initial map. The global functions all have initial maps.
281c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(prototype, Handle<Map>(function->initial_map()));
282c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the prototype from the initial map.
283c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
2847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
28757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
28857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register dst,
28957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register src,
29057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            bool inobject,
29157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            int index,
29257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Representation representation) {
293bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  ASSERT(!representation.IsDouble());
2949faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  int offset = index * kPointerSize;
2959faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  if (!inobject) {
2969faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    // Calculate the offset into the properties array.
2979faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    offset = offset + FixedArray::kHeaderSize;
2989faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
2999faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    src = dst;
300c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
3019faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(dst, FieldMemOperand(src, offset));
3025c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3055c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
3065c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Register receiver,
3075c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Register scratch,
3085c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Label* miss_label) {
309c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
310c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ JumpIfSmi(receiver, miss_label);
311c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
312c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the object is a JS array.
313c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ GetObjectType(receiver, scratch, scratch);
314c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE));
315c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
316c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load length directly from the JS array.
3178a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
318c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
319c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
320c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
321c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
3225c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
3235c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register receiver,
3245c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register scratch1,
3255c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register scratch2,
3265c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Label* miss_label) {
327c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
3288a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
329c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(v0, scratch1);
3305c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
333057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm,
334057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<JSGlobalObject> global,
335057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<Name> name,
336057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Register scratch,
337057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Label* miss) {
338057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
339e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(cell->value()->IsTheHole());
340e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ li(scratch, Operand(cell));
341f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org  __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
342e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
343e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Branch(miss, ne, scratch, Operand(at));
344e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
345e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
346e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
3472efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateNegativeHolderLookup(
348bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    MacroAssembler* masm,
349bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<JSObject> holder,
350bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Register holder_reg,
351bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
352bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Label* miss) {
353bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (holder->IsJSGlobalObject()) {
354bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateCheckPropertyCell(
355057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
356bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
357bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateDictionaryNegativeLookup(
358bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        masm, miss, holder_reg, name, scratch1(), scratch2());
359bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
360bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
361bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
362bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
363e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Generate StoreTransition code, value is passed in a0 register.
3645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// After executing generated code, the receiver_reg and name_reg
3655c838251403b0be9a882540f1922577abba4c872ager@chromium.org// may be clobbered.
3662efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
3672efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<JSObject> object,
3682efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                LookupResult* lookup,
3692efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Map> transition,
3702efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Name> name,
3712efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register receiver_reg,
3722efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register storage_reg,
3732efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register value_reg,
3742efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch1,
3752efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch2,
3762efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch3,
3772efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* miss_label,
3782efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* slow) {
379c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // a0 : value.
380c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label exit;
3817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
382f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int descriptor = transition->LastAdded();
383f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  DescriptorArray* descriptors = transition->instance_descriptors();
384f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  PropertyDetails details = descriptors->GetDetails(descriptor);
385f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = details.representation();
386f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
387f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
388fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
389fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org    Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
390057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ li(scratch1, constant);
391bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ Branch(miss_label, ne, value_reg, Operand(scratch1));
392bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  } else if (representation.IsSmi()) {
393bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
394bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  } else if (representation.IsHeapObject()) {
3958496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    __ JumpIfSmi(value_reg, miss_label);
396731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    HeapType* field_type = descriptors->GetFieldType(descriptor);
3978496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    HeapType::Iterator<Map> it = field_type->Classes();
3988496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    Handle<Map> current;
3998496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    if (!it.Done()) {
4008496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
4018496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      Label do_store;
4028496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      while (true) {
4038496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        // Do the CompareMap() directly within the Branch() functions.
4048496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        current = it.Current();
4058496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        it.Advance();
4068496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        if (it.Done()) {
4078496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org          __ Branch(miss_label, ne, scratch1, Operand(current));
4088496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org          break;
4098496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        }
4108496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        __ Branch(&do_store, eq, scratch1, Operand(current));
4118496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      }
4128496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      __ bind(&do_store);
413731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    }
414bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  } else if (representation.IsDouble()) {
41557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
41657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
41757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
41857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
41957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
42057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiUntag(scratch1, value_reg);
42157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mtc1(scratch1, f6);
42257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ cvt_d_w(f4, f6);
42357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
42457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
42557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
42657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
427bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                miss_label, DONT_DO_SMI_CHECK);
42857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
42957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
43057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&do_store);
43157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
43257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
43357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
434c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Stub never generated for non-global objects that require access
435c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // checks.
436c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
437c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
438c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Perform map transition for the receiver if necessary.
439b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  if (details.type() == FIELD &&
440b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      object->map()->unused_property_fields() == 0) {
441c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // The properties must be extended before we can store the value.
442c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // We jump to a runtime call that extends the properties array.
443c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ push(receiver_reg);
4446e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ li(a2, Operand(transition));
445c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Push(a2, a0);
446c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ TailCallExternalReference(
447c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org           ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
448c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                             masm->isolate()),
449c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org           3, 1);
450c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return;
451c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
452c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
453e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Update the map of the object.
454e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ li(scratch1, Operand(transition));
455e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
456e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
457bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Update the write barrier for the map field.
458e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ RecordWriteField(receiver_reg,
459e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      HeapObject::kMapOffset,
460e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      scratch1,
46157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      scratch2,
462e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      kRAHasNotBeenSaved,
463e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      kDontSaveFPRegs,
464e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_REMEMBERED_SET,
465e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_SMI_CHECK);
466e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
467fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
468b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    ASSERT(value_reg.is(a0));
469b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    __ Ret(USE_DELAY_SLOT);
470b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    __ mov(v0, a0);
471b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    return;
472b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  }
473b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
474e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int index = transition->instance_descriptors()->GetFieldIndex(
475e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      transition->LastAdded());
476e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
477e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Adjust for the number of properties stored in the object. Even in the
478e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // face of a transition we can use the old map here because the size of the
479e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // object and the number of in-object properties is not going to change.
480e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  index -= object->map()->inobject_properties();
481e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
482e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
483a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
484a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
485e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (index < 0) {
486e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Set the property straight into the object.
487e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = object->map()->instance_size() + (index * kPointerSize);
488bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (representation.IsDouble()) {
48957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(storage_reg, FieldMemOperand(receiver_reg, offset));
49057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
49157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
49257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
493e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
494bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (!representation.IsSmi()) {
495f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
496bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org      if (!representation.IsDouble()) {
497bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ mov(storage_reg, value_reg);
49857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
499f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(receiver_reg,
500f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
501bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                          storage_reg,
502f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          scratch1,
503f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
504a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
505a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
506a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
507f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
508f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
509e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Write to the properties array.
510e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
511e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Get the properties array
512e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ lw(scratch1,
513e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org          FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
514bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (representation.IsDouble()) {
51557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(storage_reg, FieldMemOperand(scratch1, offset));
51657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
51757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(value_reg, FieldMemOperand(scratch1, offset));
51857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
519e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
520bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (!representation.IsSmi()) {
521f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
522bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org      if (!representation.IsDouble()) {
523bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ mov(storage_reg, value_reg);
52457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
525f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(scratch1,
526f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
527bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                          storage_reg,
528f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          receiver_reg,
529f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
530a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
531a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
532a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
533f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
534e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
535e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
536e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Return the value (register v0).
537e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(value_reg.is(a0));
538e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&exit);
5398a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
540e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(v0, a0);
541e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
542e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
543e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
544e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Generate StoreField code, value is passed in a0 register.
545e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// When leaving generated code after success, the receiver_reg and name_reg
546e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// may be clobbered.  Upon branch to miss_label, the receiver and name
547e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// registers have their original values.
5482efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
5492efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Handle<JSObject> object,
5502efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           LookupResult* lookup,
5512efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register receiver_reg,
5522efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register name_reg,
5532efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register value_reg,
5542efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch1,
5552efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch2,
5562efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Label* miss_label) {
557e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // a0 : value
558e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label exit;
559e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
560e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Stub never generated for non-global objects that require access
561e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // checks.
562e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
563e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
564e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  FieldIndex index = lookup->GetFieldIndex();
565c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
566f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = lookup->representation();
567f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
568bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  if (representation.IsSmi()) {
569f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
570bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  } else if (representation.IsHeapObject()) {
5718496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    __ JumpIfSmi(value_reg, miss_label);
572731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    HeapType* field_type = lookup->GetFieldType();
5738496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    HeapType::Iterator<Map> it = field_type->Classes();
5748496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org    if (!it.Done()) {
5758496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
5768496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      Label do_store;
5778496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      Handle<Map> current;
5788496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      while (true) {
5798496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        // Do the CompareMap() directly within the Branch() functions.
5808496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        current = it.Current();
5818496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        it.Advance();
5828496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        if (it.Done()) {
5838496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org          __ Branch(miss_label, ne, scratch1, Operand(current));
5848496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org          break;
5858496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        }
5868496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        __ Branch(&do_store, eq, scratch1, Operand(current));
5878496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      }
5888496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org      __ bind(&do_store);
589731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    }
590bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  } else if (representation.IsDouble()) {
59157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Load the double storage.
592e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    if (index.is_inobject()) {
593e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      __ lw(scratch1, FieldMemOperand(receiver_reg, index.offset()));
59457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
59557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ lw(scratch1,
59657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
597e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      __ lw(scratch1, FieldMemOperand(scratch1, index.offset()));
59857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
59957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
60057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Store the value into the storage.
60157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
60257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
60357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiUntag(scratch2, value_reg);
60457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mtc1(scratch2, f6);
60557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ cvt_d_w(f4, f6);
60657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
60757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
60857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
60957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex,
610f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                miss_label, DONT_DO_SMI_CHECK);
61157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
61257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
613f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ bind(&do_store);
61457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset));
61557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Return the value (register v0).
61657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    ASSERT(value_reg.is(a0));
6178a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    __ Ret(USE_DELAY_SLOT);
61857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mov(v0, a0);
61957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    return;
620f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  }
621f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
622e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
623a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
624a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
625e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  if (index.is_inobject()) {
626c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Set the property straight into the object.
627e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    __ sw(value_reg, FieldMemOperand(receiver_reg, index.offset()));
628c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
629bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (!representation.IsSmi()) {
630f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Skip updating write barrier if storing a smi.
631f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ JumpIfSmi(value_reg, &exit);
632f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
633f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
634f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Pass the now unused name_reg as a scratch register.
635f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ mov(name_reg, value_reg);
636f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(receiver_reg,
637e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                          index.offset(),
638f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          name_reg,
639f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          scratch1,
640f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
641a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
642a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
643a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
644f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
645c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
646c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Write to the properties array.
647c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Get the properties array.
6487028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ lw(scratch1,
6497028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
650e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    __ sw(value_reg, FieldMemOperand(scratch1, index.offset()));
651c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
652bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    if (!representation.IsSmi()) {
653f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Skip updating write barrier if storing a smi.
654f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ JumpIfSmi(value_reg, &exit);
655f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
656f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
657f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Ok to clobber receiver_reg and name_reg, since we return.
658f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ mov(name_reg, value_reg);
659f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(scratch1,
660e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                          index.offset(),
661f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          name_reg,
662f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          receiver_reg,
663f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
664a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
665a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
666a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
667f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
668c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
669c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
670c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the value (register v0).
6712bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ASSERT(value_reg.is(a0));
672c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&exit);
6738a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
674c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(v0, a0);
6755c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
6765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6782efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
6792efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Label* label,
6802efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Handle<Name> name) {
6812bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  if (!label->is_unused()) {
6822bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ bind(label);
6832bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ li(this->name(), Operand(name));
6842bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  }
685068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org}
686068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
687068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
688c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void PushInterceptorArguments(MacroAssembler* masm,
689c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register receiver,
690c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register holder,
691c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register name,
692c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                     Handle<JSObject> holder_obj) {
6934a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0);
6944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1);
6954a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2);
6964a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3);
6974a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4);
698c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(name);
699c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
700c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
701c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register scratch = name;
702c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ li(scratch, Operand(interceptor));
703c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Push(scratch, receiver, holder);
704c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
705c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
706c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
707c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void CompileCallLoadPropertyWithInterceptor(
708c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
709c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register receiver,
710c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register holder,
711c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register name,
71237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    Handle<JSObject> holder_obj,
71337be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    IC::UtilityId id) {
714c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
71537be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org  __ CallExternalReference(
71637be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      ExternalReference(IC_Utility(id), masm->isolate()),
71737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      StubCache::kInterceptorArgsLength);
718c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
719c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
720c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
7216f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org// Generate call to api function.
722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid StubCompiler::GenerateFastApiCall(MacroAssembler* masm,
723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       const CallOptimization& optimization,
724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       Handle<Map> receiver_map,
725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       Register receiver,
726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       Register scratch_in,
727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       bool is_store,
728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       int argc,
729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                       Register* values) {
7306f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  ASSERT(!receiver.is(scratch_in));
7316f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  // Preparing to push, adjust sp.
7326f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  __ Subu(sp, sp, Operand((argc + 1) * kPointerSize));
7336f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  __ sw(receiver, MemOperand(sp, argc * kPointerSize));  // Push receiver.
7346f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  // Write the arguments to stack frame.
7356f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  for (int i = 0; i < argc; i++) {
7366f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    Register arg = values[argc-1-i];
7376f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    ASSERT(!receiver.is(arg));
7386f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    ASSERT(!scratch_in.is(arg));
7396f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    __ sw(arg, MemOperand(sp, (argc-1-i) * kPointerSize));  // Push arg.
7406f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  }
741cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com  ASSERT(optimization.is_simple_api_call());
742cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com
743e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Abi for CallApiFunctionStub.
744e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  Register callee = a0;
745e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  Register call_data = t0;
746e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  Register holder = a2;
74757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  Register api_function_address = a1;
748cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com
749e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Put holder in place.
7506f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  CallOptimization::HolderLookup holder_lookup;
7516f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
7526f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      receiver_map,
7536f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      &holder_lookup);
7546f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  switch (holder_lookup) {
7556f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    case CallOptimization::kHolderIsReceiver:
7566f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      __ Move(holder, receiver);
7576f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      break;
7586f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    case CallOptimization::kHolderFound:
7596f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      __ li(holder, api_holder);
7606f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org     break;
7616f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    case CallOptimization::kHolderNotFound:
7626f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      UNREACHABLE();
7636f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      break;
7646f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  }
765cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com
766e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  Isolate* isolate = masm->isolate();
767c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function = optimization.constant_function();
768c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
769e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  Handle<Object> call_data_obj(api_call_info->data(), isolate);
770e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org
771e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Put callee in place.
772e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  __ li(callee, function);
773e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org
774cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com  bool call_data_undefined = false;
775e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Put call_data in place.
776e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  if (isolate->heap()->InNewSpace(*call_data_obj)) {
777e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org    __ li(call_data, api_call_info);
778e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org    __ lw(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset));
779e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  } else if (call_data_obj->IsUndefined()) {
780cc96b0ea1fd0249c4914f68201fc8a7a93d7b9b2palfia@homejinni.com    call_data_undefined = true;
781e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org    __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
782c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
783e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org    __ li(call_data, call_data_obj);
784c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
785e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Put api_function_address in place.
786662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address function_address = v8::ToCData<Address>(api_call_info->callback());
787c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ApiFunction fun(function_address);
788662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
789c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference ref =
790c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference(&fun,
791bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                        type,
792c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                        masm->isolate());
793e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  __ li(api_function_address, Operand(ref));
794fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org
795e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  // Jump to stub.
796f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
797e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  __ TailCallStub(&stub);
798c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
799c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
800639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
8012bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
8029faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ Jump(code, RelocInfo::CODE_TARGET);
8039faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org}
8049faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
8059faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
8062bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#undef __
8072bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#define __ ACCESS_MASM(masm())
8082bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
8092bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
8106d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.orgRegister StubCompiler::CheckPrototypes(Handle<HeapType> type,
811394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register object_reg,
812394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Handle<JSObject> holder,
813394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register holder_reg,
814394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch1,
815394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch2,
8169faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       Handle<Name> name,
8179faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       Label* miss,
8189faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       PrototypeCheckType check) {
819f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
820ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
821394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Make sure there's no overlap between holder and object registers.
822394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
823394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
824394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         && !scratch2.is(scratch1));
825394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
826394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Keep track of the current object in register reg.
827394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register reg = object_reg;
828394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  int depth = 0;
829394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
830f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> current = Handle<JSObject>::null();
831fa04143c1ab67009bfa167c48e1cf21fdf009796palfia@homejinni.com  if (type->IsConstant()) {
832fa04143c1ab67009bfa167c48e1cf21fdf009796palfia@homejinni.com    current = Handle<JSObject>::cast(type->AsConstant()->Value());
833fa04143c1ab67009bfa167c48e1cf21fdf009796palfia@homejinni.com  }
834f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> prototype = Handle<JSObject>::null();
835f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> current_map = receiver_map;
836f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> holder_map(holder->map());
837f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Traverse the prototype chain and check the maps in the prototype chain for
838f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // fast and global objects or do negative lookup for normal objects.
839f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  while (!current_map.is_identical_to(holder_map)) {
840394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ++depth;
841394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
842394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Only global objects and objects that do not require access
843394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // checks are allowed in stubs.
844f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    ASSERT(current_map->IsJSGlobalProxyMap() ||
845f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org           !current_map->is_access_check_needed());
846394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
847f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    prototype = handle(JSObject::cast(current_map->prototype()));
848f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    if (current_map->is_dictionary_map() &&
849f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalObjectMap() &&
850f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalProxyMap()) {
8519faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      if (!name->IsUniqueName()) {
8529faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        ASSERT(name->IsString());
8539faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        name = factory()->InternalizeString(Handle<String>::cast(name));
854394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
855f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      ASSERT(current.is_null() ||
856f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org             current->property_dictionary()->FindEntry(name) ==
8579faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org             NameDictionary::kNotFound);
858394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
859394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
860394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       scratch1, scratch2);
861394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
862394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
863394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
864394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
865394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    } else {
8669faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      Register map_reg = scratch1;
867f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (depth != 1 || check == CHECK_ALL_MAPS) {
8689faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        // CheckMap implicitly loads the map of |reg| into |map_reg|.
869a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
8709faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      } else {
8719faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
8729faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      }
873f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
874394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Check access rights to the global object.  This has to happen after
875394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // the map check so that we know that the object is actually a global
876394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // object.
877f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (current_map->IsJSGlobalProxyMap()) {
878394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ CheckAccessGlobalProxy(reg, scratch2, miss);
879f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      } else if (current_map->IsJSGlobalObjectMap()) {
880f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        GenerateCheckPropertyCell(
881f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            masm(), Handle<JSGlobalObject>::cast(current), name,
882f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            scratch2, miss);
883394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
884f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
885394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
886394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
887394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (heap()->InNewSpace(*prototype)) {
888394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in new space; we cannot store a reference to it
889394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // in the code.  Load it from the map.
8909faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
891394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      } else {
892394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in old space; load it directly.
893394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ li(reg, Operand(prototype));
894394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
895394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    }
896394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
897394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Go to the next object in the prototype chain.
898394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    current = prototype;
899f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    current_map = handle(current->map());
900394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
901394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
902394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Log the check depth.
90332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
904394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
905f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (depth != 0 || check == CHECK_ALL_MAPS) {
9069faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    // Check the holder map.
907f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK);
9089faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
909394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
910394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Perform security check for access to the global object.
911f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  ASSERT(current_map->IsJSGlobalProxyMap() ||
912f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org         !current_map->is_access_check_needed());
913f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (current_map->IsJSGlobalProxyMap()) {
914394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ CheckAccessGlobalProxy(reg, scratch1, miss);
915394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
916394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
917394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Return the register containing the holder.
918394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  return reg;
919394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
920394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
921394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
922b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
9239faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  if (!miss->is_unused()) {
924b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
925b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ Branch(&success);
9269faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    __ bind(miss);
9272bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
928b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
9299faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
9305c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
9315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
933b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
934bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (!miss->is_unused()) {
935b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
936b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ Branch(&success);
937bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateRestoreName(masm(), miss, name);
938bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
939b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
940bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
941bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
942bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
943bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
9442efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgRegister LoadStubCompiler::CallbackHandlerFrontend(
9456d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org    Handle<HeapType> type,
9464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register object_reg,
9474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<JSObject> holder,
9489faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
9492c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    Handle<Object> callback) {
9504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label miss;
951c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
952f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
9535c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
9554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch2()));
9564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch3()));
9574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch4()));
9584a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
9594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Load the properties dictionary.
9604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register dictionary = scratch4();
9614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset));
9624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
9634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Probe the dictionary.
9644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Label probe_done;
9659faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
9669faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     &miss,
9679faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     &probe_done,
9689faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     dictionary,
9699faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     this->name(),
9709faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     scratch2(),
9719faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     scratch3());
9724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ bind(&probe_done);
9734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
9744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // If probing finds an entry in the dictionary, scratch3 contains the
9754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // pointer into the dictionary. Check that the value is the callback.
9764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register pointer = scratch3();
9779faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    const int kElementsStartOffset = NameDictionary::kHeaderSize +
9789faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        NameDictionary::kElementsStartIndex * kPointerSize;
9794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    const int kValueOffset = kElementsStartOffset + kPointerSize;
9804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset));
9814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ Branch(&miss, ne, scratch2(), Operand(callback));
9824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  }
9835c838251403b0be9a882540f1922577abba4c872ager@chromium.org
984b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  HandlerFrontendFooter(name, &miss);
9854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  return reg;
986471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org}
987471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org
988471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org
9892efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadField(Register reg,
9902efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                         Handle<JSObject> holder,
991e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org                                         FieldIndex field,
9922efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                         Representation representation) {
99357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (!reg.is(receiver())) __ mov(receiver(), reg);
99457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (kind() == Code::LOAD_IC) {
995e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    LoadFieldStub stub(isolate(), field);
996f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    GenerateTailCall(masm(), stub.GetCode());
99757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  } else {
998e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org    KeyedLoadFieldStub stub(isolate(), field);
999f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    GenerateTailCall(masm(), stub.GetCode());
100057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
10014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
10024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
10034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
10042efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
10054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Return the constant value.
1006057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ li(v0, value);
10074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Ret();
10084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
10094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
10104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
10112efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadCallback(
10124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register reg,
10134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<ExecutableAccessorInfo> callback) {
1014c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Build AccessorInfo::args_ list on the stack and push property name below
1015c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // the exit frame to make GC aware of them and store pointers to them.
1016fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
1017fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
1018fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
1019fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
1020fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
1021fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
1022fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
10234a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch2().is(reg));
10244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch3().is(reg));
10254a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch4().is(reg));
10264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ push(receiver());
1027c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (heap()->InNewSpace(callback->data())) {
10284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ li(scratch3(), callback);
10294a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(scratch3(), FieldMemOperand(scratch3(),
10304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                      ExecutableAccessorInfo::kDataOffset));
1031c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
103232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ li(scratch3(), Handle<Object>(callback->data(), isolate()));
1033c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
103479d0bf7c99ebe30751b199f72fa06fe34a5ded48palfia@homejinni.com  __ Subu(sp, sp, 6 * kPointerSize);
10354a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch3(), MemOperand(sp, 5 * kPointerSize));
1036c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org  __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
10374a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch3(), MemOperand(sp, 4 * kPointerSize));
103879d0bf7c99ebe30751b199f72fa06fe34a5ded48palfia@homejinni.com  __ sw(scratch3(), MemOperand(sp, 3 * kPointerSize));
1039c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org  __ li(scratch4(),
104032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        Operand(ExternalReference::isolate_address(isolate())));
10414a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch4(), MemOperand(sp, 2 * kPointerSize));
10424a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(reg, MemOperand(sp, 1 * kPointerSize));
10434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ sw(name(), MemOperand(sp, 0 * kPointerSize));
1044fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ Addu(scratch2(), sp, 1 * kPointerSize);
1045ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
10464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(a2, scratch2());  // Saved in case scratch2 == a1.
104757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  // Abi for CallApiGetter.
104857a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  Register getter_address_reg = a2;
1049c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1050662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address getter_address = v8::ToCData<Address>(callback->getter());
1051c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ApiFunction fun(getter_address);
1052662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1053fe578677d80b14b35f6dca0c193719331b81a81edanno@chromium.org  ExternalReference ref = ExternalReference(&fun, type, isolate());
1054e014e5bf9ccd6a759add3b35ba610f3a0c752a90machenbach@chromium.org  __ li(getter_address_reg, Operand(ref));
105557a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org
1056f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  CallApiGetterStub stub(isolate());
105757a54ace4b6b45d5d6a7ff38d88ee9990d47f5e2machenbach@chromium.org  __ TailCallStub(&stub);
10585c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10612efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadInterceptor(
10624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register holder_reg,
1063b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Handle<Object> object,
10644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<JSObject> interceptor_holder,
10654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    LookupResult* lookup,
10669faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name) {
1067c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(interceptor_holder->HasNamedInterceptor());
1068c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1069c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1070c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // So far the most popular follow ups for interceptor loads are FIELD
1071c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // and CALLBACKS, so inline only them, other cases may be added
1072c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // later.
1073c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  bool compile_followup_inline = false;
107405ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org  if (lookup->IsFound() && lookup->IsCacheable()) {
1075de0db002768654f346a9059d80ab47602018bfa0yangguo@chromium.org    if (lookup->IsField()) {
1076c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      compile_followup_inline = true;
1077c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else if (lookup->type() == CALLBACKS &&
1078c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org        lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
1079c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org      ExecutableAccessorInfo* callback =
1080c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org          ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
10817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      compile_followup_inline = callback->getter() != NULL &&
10827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          callback->IsCompatibleReceiver(*object);
1083c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1084c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1085c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1086c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (compile_followup_inline) {
1087c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Compile the interceptor call, followed by inline code to load the
1088c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // property from further up the prototype chain if the call fails.
1089c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps haven't changed.
10904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1091c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1092212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // Preserve the receiver register explicitly whenever it is different from
1093212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the holder and it is needed should the interceptor return without any
1094212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1095212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the FIELD case might cause a miss during the prototype check.
1096212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
10974a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1098212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1099212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org
1100c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Save necessary data before invoking an interceptor.
1101c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Requires a frame to make GC aware of pushed pointers.
1102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1103c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1104212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
11054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ Push(receiver(), holder_reg, this->name());
1106c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      } else {
11074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ Push(holder_reg, this->name());
1108c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1109c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Invoke an interceptor.  Note: map checks from receiver to
1110c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // interceptor's holder has been compiled before (see a caller
1111c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // of this method).
111237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      CompileCallLoadPropertyWithInterceptor(
111337be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
111437be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          IC::kLoadPropertyWithInterceptorOnly);
111537be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org
1116c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if interceptor provided a value for property.  If it's
1117c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // the case, return immediately.
1118c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Label interceptor_failed;
11194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
11204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
1121c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      frame_scope.GenerateLeaveFrame();
1122c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Ret();
1123c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1124c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ bind(&interceptor_failed);
11254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ pop(this->name());
1126c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pop(holder_reg);
1127212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
11284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ pop(receiver());
1129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Leave the internal frame.
1131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
11324a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1133c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {  // !compile_followup_inline
1134c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Call the runtime system to load the interceptor.
1135c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps haven't changed.
11364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    PushInterceptorArguments(masm(), receiver(), holder_reg,
11374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                             this->name(), interceptor_holder);
1138c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1139c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ExternalReference ref = ExternalReference(
11408ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org        IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
11414a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1142c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
11435c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
11445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11466e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreCallback(
11474c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org    Handle<JSObject> object,
1148355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    Handle<JSObject> holder,
1149bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
1150c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org    Handle<ExecutableAccessorInfo> callback) {
115143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  Register holder_reg = HandlerFrontend(
115243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1153c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1154c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Stub never generated for non-global objects that require access
1155c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // checks.
1156355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1157c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
11586f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  __ Push(receiver(), holder_reg);  // Receiver.
11594c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ li(at, Operand(callback));  // Callback info.
1160bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ push(at);
1161bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ li(at, Operand(name));
1162bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ Push(at, value());
1163c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1164c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Do tail-call to the runtime system.
1165c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference store_callback_property =
116632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
116743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ TailCallExternalReference(store_callback_property, 5, 1);
1168c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1169c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
11709af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
11717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
11727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
117446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
117546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm)
117646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
117746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
117846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orgvoid StoreStubCompiler::GenerateStoreViaSetter(
117946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    MacroAssembler* masm,
118025530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org    Handle<HeapType> type,
1181bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    Register receiver,
1182619781ad24991bca2894d2f677ac960da366b11esvenpanne@chromium.org    Handle<JSFunction> setter) {
11837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // ----------- S t a t e -------------
11847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- ra    : return address
11857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // -----------------------------------
11867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
118746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
11887028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
11897028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Save value register, so we can restore it later.
1190bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    __ push(value());
11917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
119246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    if (!setter.is_null()) {
119346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // Call the JavaScript setter with receiver and value on the stack.
119425530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
119525530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org        // Swap in the global receiver.
119625530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org        __ lw(receiver,
119725530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org               FieldMemOperand(
119825530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org                   receiver, JSGlobalObject::kGlobalReceiverOffset));
119925530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org      }
1200bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org      __ Push(receiver, value());
120146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      ParameterCount actual(1);
120232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(setter);
120332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(setter, expected, actual,
1204e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                        CALL_FUNCTION, NullCallWrapper());
120546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    } else {
120646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // If we generate a global code snippet for deoptimization only, remember
120746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // the place to continue after deoptimization.
120846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
120946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    }
12107028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
12117028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // We have to return the passed value, not the return value of the setter.
12127028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ pop(v0);
12137028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
12147028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Restore context register.
12157028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
12167028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
12177028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Ret();
121846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
121946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
122046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
122146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
122246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm())
122346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
122446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
12256e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
12264c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org    Handle<JSObject> object,
12279faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name) {
12284c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ Push(receiver(), this->name(), value());
1229c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1230c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Do tail-call to the runtime system.
1231c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference store_ic_property =
123232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
1233cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ TailCallExternalReference(store_ic_property, 3, 1);
1234c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1235c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
12369af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
12377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12406d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.orgHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
1241f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<JSObject> last,
1242f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<Name> name) {
1243f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  NonexistentHandlerFrontend(type, last, name);
124494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
1245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return undefined if maps of the full prototype chain is still the same.
1246c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
1247c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Ret();
1248c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1249c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
12509af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
12517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
125494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* LoadStubCompiler::registers() {
125594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
125694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { a0, a2, a3, a1, t0, t1 };
125794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
125894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org}
1259c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1260c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
126194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* KeyedLoadStubCompiler::registers() {
126294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
126394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { a1, a0, a2, a3, t0, t1 };
126494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
12655c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12665c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1268bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.orgRegister StoreStubCompiler::value() {
1269bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  return a0;
1270bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org}
1271bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org
1272bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org
12732bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* StoreStubCompiler::registers() {
1274bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  // receiver, name, scratch1, scratch2, scratch3.
1275bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  static Register registers[] = { a1, a2, a3, t0, t1 };
12762bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
12772bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
12782bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
12792bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
12802bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* KeyedStoreStubCompiler::registers() {
1281bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  // receiver, name, scratch1, scratch2, scratch3.
1282bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  static Register registers[] = { a2, a1, a3, t0, t1 };
12832bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
12842bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
12852bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
12862bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
1287de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
1288de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm)
1289de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1290de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1291de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
129225530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org                                             Handle<HeapType> type,
12932efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                             Register receiver,
1294de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org                                             Handle<JSFunction> getter) {
1295de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // ----------- S t a t e -------------
1296de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- a0    : receiver
1297de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- a2    : name
1298de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- ra    : return address
1299de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // -----------------------------------
1300de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  {
1301de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
1302de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1303de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    if (!getter.is_null()) {
1304de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // Call the JavaScript getter with the receiver on the stack.
130525530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
130625530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org        // Swap in the global receiver.
130725530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org        __ lw(receiver,
130825530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org                FieldMemOperand(
130925530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org                    receiver, JSGlobalObject::kGlobalReceiverOffset));
131025530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org      }
13112efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org      __ push(receiver);
1312de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      ParameterCount actual(0);
131332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(getter);
131432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(getter, expected, actual,
1315e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org                        CALL_FUNCTION, NullCallWrapper());
1316de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    } else {
1317de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // If we generate a global code snippet for deoptimization only, remember
1318de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // the place to continue after deoptimization.
1319de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
1320de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
1321de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1322de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    // Restore context register.
1323de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1324de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  }
1325de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ Ret();
1326de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org}
1327de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1328de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1329de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
1330de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm())
1331de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
1332de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
13336e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> LoadStubCompiler::CompileLoadGlobal(
13346d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org    Handle<HeapType> type,
13354a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<GlobalObject> global,
1336b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    Handle<PropertyCell> cell,
13379faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
13386e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    bool is_dont_delete) {
1339b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label miss;
1340c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1341f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontendHeader(type, receiver(), global, name, &miss);
1342c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1343c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the value from the cell.
13446e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  __ li(a3, Operand(cell));
1345f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org  __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset));
1346c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1347c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check for deleted property if property can actually be deleted.
1348c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (!is_dont_delete) {
1349c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1350c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&miss, eq, t0, Operand(at));
1351c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1352c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
135332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  Counters* counters = isolate()->counters();
1354c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
13558a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
13564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(v0, t0);
1357c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1358a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  HandlerFrontendFooter(name, &miss);
1359a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
1360c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
1361e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  return GetCode(kind(), Code::NORMAL, name);
13625c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
13637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1365bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgHandle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
1366af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    TypeHandleList* types,
13679faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    CodeHandleList* handlers,
13689faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
13699faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Code::StubType type,
13709faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    IcCheckType check) {
137140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  Label miss;
13729faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
137343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  if (check == PROPERTY &&
137443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
137543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ Branch(&miss, ne, this->name(), Operand(name));
13769faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
13779faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
1378b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label number_case;
13793a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org  Register match = scratch1();
1380af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
13813a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org  __ JumpIfSmi(receiver(), smi_target, match);  // Reg match is 0 if Smi.
1382b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
13833a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org  Register map_reg = scratch2();
1384c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1385af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  int receiver_count = types->length();
1386f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int number_of_handled_maps = 0;
13879faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
138840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  for (int current = 0; current < receiver_count; ++current) {
13896d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org    Handle<HeapType> type = types->at(current);
1390af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    Handle<Map> map = IC::TypeToMap(*type, isolate());
1391f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!map->is_deprecated()) {
1392f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps++;
13933a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org      // Check map and tail call if there's a match.
13943a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org      // Separate compare from branch, to provide path for above JumpIfSmi().
13953a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org      __ Subu(match, map_reg, Operand(map));
13966d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org      if (type->Is(HeapType::Number())) {
1397b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        ASSERT(!number_case.is_unused());
1398b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        __ bind(&number_case);
1399b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      }
1400f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ Jump(handlers->at(current), RelocInfo::CODE_TARGET,
14013a9c5d9b20b1897a1acd41dbad9e724c504a4db9machenbach@chromium.org          eq, match, Operand(zero_reg));
1402f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
140340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
1404f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(number_of_handled_maps != 0);
1405c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1406c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
14072bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
1408c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1409c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
14109faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  InlineCacheState state =
1411f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
14129faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  return GetICCode(kind(), type, name, state);
14137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
14162904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.orgvoid StoreStubCompiler::GenerateStoreArrayLength() {
14172904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  // Prepare tail call to StoreIC_ArrayLength.
14182904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  __ Push(receiver(), value());
14192904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
14202904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  ExternalReference ref =
14212904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength),
14222904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org                        masm()->isolate());
14232904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  __ TailCallExternalReference(ref, 2, 1);
14242904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org}
14252904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
14262904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
14276e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
14286e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    MapHandleList* receiver_maps,
14296e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    CodeHandleList* handler_stubs,
14306e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    MapHandleList* transitioned_maps) {
143140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  Label miss;
14324c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ JumpIfSmi(receiver(), &miss);
143340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
143440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  int receiver_count = receiver_maps->length();
14354c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
1436b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  for (int i = 0; i < receiver_count; ++i) {
14376e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    if (transitioned_maps->at(i).is_null()) {
14386e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq,
14394c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org          scratch1(), Operand(receiver_maps->at(i)));
1440b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    } else {
1441b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      Label next_map;
14424c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org      __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
14434c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org      __ li(transition_map(), Operand(transitioned_maps->at(i)));
14446e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
1445b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ bind(&next_map);
1446b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    }
1447c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1448c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1449c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
14502bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
1451c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1452c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
14532bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return GetICCode(
14542bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
14555c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
145840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org#undef __
145940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org#define __ ACCESS_MASM(masm)
146040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
146140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
14626db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.orgvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
14636db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    MacroAssembler* masm) {
14646db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
14656db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
14666db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
14676db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
14686db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
1469af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label slow, miss;
14706db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
14716db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Register key = a0;
14726db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Register receiver = a1;
14736db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
1474af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ JumpIfNotSmi(key, &miss);
14756db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
14766db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ sra(a2, a0, kSmiTagSize);
14776db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
14786db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ Ret();
14796db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
14806db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Slow case, key and receiver still in a0 and a1.
14816db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ bind(&slow);
14826db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ IncrementCounter(
14836db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      masm->isolate()->counters()->keyed_load_external_array_slow(),
14846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      1, a2, a3);
14856db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Entry registers are intact.
14866db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
14876db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
14886db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
14896db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
14906db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
14912bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
14926db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
14936db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Miss case, call the runtime.
1494af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ bind(&miss);
14956db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
14966db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
14976db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
14986db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
14996db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
15006db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
1501af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
15026db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org}
15036db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
15046db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
15055c838251403b0be9a882540f1922577abba4c872ager@chromium.org#undef __
15065c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15075c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
15085c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15099dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_MIPS
1510