blob: 0a887d5fafe7ed33a40233056b096d8a5f636e38 [file] [log] [blame]
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
ager@chromium.org65dad4b2009-04-23 08:48:43 +000037#define __ ACCESS_MASM(masm)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39
40static void ProbeTable(MacroAssembler* masm,
41 Code::Flags flags,
42 StubCache::Table table,
43 Register name,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000044 Register offset,
45 Register extra) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046 ExternalReference key_offset(SCTableReference::keyReference(table));
47 ExternalReference value_offset(SCTableReference::valueReference(table));
48
49 Label miss;
50
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000051 if (extra.is_valid()) {
52 // Get the code entry from the cache.
53 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000054
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000055 // Check that the key in the entry matches the name.
56 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
57 __ j(not_equal, &miss, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000058
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000059 // Check that the flags match what we're looking for.
60 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
61 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
62 __ cmp(offset, flags);
63 __ j(not_equal, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000064
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000065 // Jump to the first instruction in the code stub.
66 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
67 __ jmp(Operand(extra));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000069 __ bind(&miss);
70 } else {
71 // Save the offset on the stack.
72 __ push(offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000074 // Check that the key in the entry matches the name.
75 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
76 __ j(not_equal, &miss, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000078 // Get the code entry from the cache.
79 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
80
81 // Check that the flags match what we're looking for.
82 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
83 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
84 __ cmp(offset, flags);
85 __ j(not_equal, &miss);
86
87 // Restore offset and re-load code entry from cache.
88 __ pop(offset);
89 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
90
91 // Jump to the first instruction in the code stub.
92 __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
93 __ jmp(Operand(offset));
94
95 // Pop at miss.
96 __ bind(&miss);
97 __ pop(offset);
98 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099}
100
101
102void StubCache::GenerateProbe(MacroAssembler* masm,
103 Code::Flags flags,
104 Register receiver,
105 Register name,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000106 Register scratch,
107 Register extra) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 Label miss;
109
110 // Make sure that code is valid. The shifting code relies on the
111 // entry size being 8.
112 ASSERT(sizeof(Entry) == 8);
113
114 // Make sure the flags does not name a specific type.
115 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
116
117 // Make sure that there are no register conflicts.
118 ASSERT(!scratch.is(receiver));
119 ASSERT(!scratch.is(name));
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000120 ASSERT(!extra.is(receiver));
121 ASSERT(!extra.is(name));
122 ASSERT(!extra.is(scratch));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123
124 // Check that the receiver isn't a smi.
125 __ test(receiver, Immediate(kSmiTagMask));
126 __ j(zero, &miss, not_taken);
127
128 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000129 __ mov(scratch, FieldOperand(name, String::kLengthOffset));
130 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131 __ xor_(scratch, flags);
132 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
133
134 // Probe the primary table.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000135 ProbeTable(masm, flags, kPrimary, name, scratch, extra);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136
137 // Primary miss: Compute hash for secondary probe.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000138 __ mov(scratch, FieldOperand(name, String::kLengthOffset));
139 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
140 __ xor_(scratch, flags);
141 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142 __ sub(scratch, Operand(name));
143 __ add(Operand(scratch), Immediate(flags));
144 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
145
146 // Probe the secondary table.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000147 ProbeTable(masm, flags, kSecondary, name, scratch, extra);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148
149 // Cache miss: Fall-through and let caller handle the miss by
150 // entering the runtime system.
151 __ bind(&miss);
152}
153
154
155void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
156 int index,
157 Register prototype) {
158 // Load the global or builtins object from the current context.
159 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
160 // Load the global context from the global or builtins object.
161 __ mov(prototype,
162 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
163 // Load the function from the global context.
164 __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
165 // Load the initial map. The global functions all have initial maps.
166 __ mov(prototype,
167 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
168 // Load the prototype from the initial map.
169 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
170}
171
172
173void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
174 Register receiver,
175 Register scratch,
176 Label* miss_label) {
177 // Check that the receiver isn't a smi.
178 __ test(receiver, Immediate(kSmiTagMask));
179 __ j(zero, miss_label, not_taken);
180
181 // Check that the object is a JS array.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000182 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183 __ j(not_equal, miss_label, not_taken);
184
185 // Load length directly from the JS array.
186 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
187 __ ret(0);
188}
189
190
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000191// Generate code to check if an object is a string. If the object is
192// a string, the map's instance type is left in the scratch register.
193static void GenerateStringCheck(MacroAssembler* masm,
194 Register receiver,
195 Register scratch,
196 Label* smi,
197 Label* non_string_object) {
198 // Check that the object isn't a smi.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199 __ test(receiver, Immediate(kSmiTagMask));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000200 __ j(zero, smi, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000202 // Check that the object is a string.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
204 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000205 ASSERT(kNotStringTag != 0);
206 __ test(scratch, Immediate(kNotStringTag));
207 __ j(not_zero, non_string_object, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208}
209
210
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000211void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
212 Register receiver,
213 Register scratch,
214 Label* miss) {
215 Label load_length, check_wrapper;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000217 // Check if the object is a string leaving the instance type in the
218 // scratch register.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000219 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220
221 // Load length directly from the string.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000222 __ bind(&load_length);
223 __ and_(scratch, kStringSizeMask);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000225 // ecx is also the receiver.
226 __ lea(ecx, Operand(scratch, String::kLongLengthShift));
227 __ shr(eax); // ecx is implicit shift register.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228 __ shl(eax, kSmiTagSize);
229 __ ret(0);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000230
231 // Check if the object is a JSValue wrapper.
232 __ bind(&check_wrapper);
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000233 __ cmp(scratch, JS_VALUE_TYPE);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000234 __ j(not_equal, miss, not_taken);
235
236 // Check if the wrapped value is a string and load the length
237 // directly if it is.
238 __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
239 GenerateStringCheck(masm, receiver, scratch, miss, miss);
240 __ jmp(&load_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241}
242
243
244void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
245 Register receiver,
246 Register scratch1,
247 Register scratch2,
248 Label* miss_label) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000249 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250 __ mov(eax, Operand(scratch1));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251 __ ret(0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000252}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
ager@chromium.org7c537e22008-10-16 08:43:32 +0000254
255// Load a fast property out of a holder object (src). In-object properties
256// are loaded directly otherwise the property is loaded from the properties
257// fixed array.
258void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000259 Register dst, Register src,
260 JSObject* holder, int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000261 // Adjust for the number of properties stored in the holder.
262 index -= holder->map()->inobject_properties();
263 if (index < 0) {
264 // Get the property straight out of the holder.
265 int offset = holder->map()->instance_size() + (index * kPointerSize);
266 __ mov(dst, FieldOperand(src, offset));
267 } else {
268 // Calculate the offset into the properties array.
269 int offset = index * kPointerSize + Array::kHeaderSize;
270 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
271 __ mov(dst, FieldOperand(dst, offset));
272 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273}
274
275
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000276
277
278void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
279 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
280 Code* code = NULL;
281 if (kind == Code::LOAD_IC) {
282 code = Builtins::builtin(Builtins::LoadIC_Miss);
283 } else {
284 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
285 }
286
287 Handle<Code> ic(code);
ager@chromium.org236ad962008-09-25 09:45:57 +0000288 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289}
290
291
292void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000293 Builtins::Name storage_extend,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000294 JSObject* object,
295 int index,
296 Map* transition,
297 Register receiver_reg,
298 Register name_reg,
299 Register scratch,
300 Label* miss_label) {
301 // Check that the object isn't a smi.
302 __ test(receiver_reg, Immediate(kSmiTagMask));
303 __ j(zero, miss_label, not_taken);
304
305 // Check that the map of the object hasn't changed.
306 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
307 Immediate(Handle<Map>(object->map())));
308 __ j(not_equal, miss_label, not_taken);
309
310 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000311 if (object->IsJSGlobalProxy()) {
312 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313 }
314
315 // Stub never generated for non-global objects that require access
316 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000317 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000319 // Perform map transition for the receiver if necessary.
320 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
321 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000322 // We jump to a runtime call that extends the properties array.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000323 __ mov(ecx, Immediate(Handle<Map>(transition)));
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000324 Handle<Code> ic(Builtins::builtin(storage_extend));
325 __ jmp(ic, RelocInfo::CODE_TARGET);
326 return;
327 }
328
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329 if (transition != NULL) {
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000330 // Update the map of the object; no write barrier updating is
331 // needed because the map is never in new space.
332 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
333 Immediate(Handle<Map>(transition)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334 }
335
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000336 // Adjust for the number of properties stored in the object. Even in the
337 // face of a transition we can use the old map here because the size of the
338 // object and the number of in-object properties is not going to change.
339 index -= object->map()->inobject_properties();
340
ager@chromium.org7c537e22008-10-16 08:43:32 +0000341 if (index < 0) {
342 // Set the property straight into the object.
343 int offset = object->map()->instance_size() + (index * kPointerSize);
344 __ mov(FieldOperand(receiver_reg, offset), eax);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000345
ager@chromium.org7c537e22008-10-16 08:43:32 +0000346 // Update the write barrier for the array address.
347 // Pass the value being stored in the now unused name_reg.
348 __ mov(name_reg, Operand(eax));
349 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
350 } else {
351 // Write to the properties array.
352 int offset = index * kPointerSize + Array::kHeaderSize;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000353 // Get the properties array (optimistically).
354 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
ager@chromium.org7c537e22008-10-16 08:43:32 +0000355 __ mov(FieldOperand(scratch, offset), eax);
356
357 // Update the write barrier for the array address.
358 // Pass the value being stored in the now unused name_reg.
359 __ mov(name_reg, Operand(eax));
360 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
361 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362
363 // Return the value (register eax).
364 __ ret(0);
365}
366
367
368#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000369#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370
371
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000372Register StubCompiler::CheckPrototypes(JSObject* object,
373 Register object_reg,
374 JSObject* holder,
375 Register holder_reg,
376 Register scratch,
377 String* name,
378 Label* miss) {
379 // Check that the maps haven't changed.
380 Register result =
381 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
382
383 // If we've skipped any global objects, it's not enough to verify
384 // that their maps haven't changed.
385 while (object != holder) {
386 if (object->IsGlobalObject()) {
387 GlobalObject* global = GlobalObject::cast(object);
388 Object* probe = global->EnsurePropertyCell(name);
389 if (probe->IsFailure()) {
390 set_failure(Failure::cast(probe));
391 return result;
392 }
393 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
394 ASSERT(cell->value()->IsTheHole());
395 __ mov(scratch, Immediate(Handle<Object>(cell)));
396 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
397 Immediate(Factory::the_hole_value()));
398 __ j(not_equal, miss, not_taken);
399 }
400 object = JSObject::cast(object->GetPrototype());
401 }
402
403 // Return the register containin the holder.
404 return result;
405}
406
407
408void StubCompiler::GenerateLoadField(JSObject* object,
409 JSObject* holder,
410 Register receiver,
411 Register scratch1,
412 Register scratch2,
413 int index,
414 String* name,
415 Label* miss) {
416 // Check that the receiver isn't a smi.
417 __ test(receiver, Immediate(kSmiTagMask));
418 __ j(zero, miss, not_taken);
419
420 // Check the prototype chain.
421 Register reg =
422 CheckPrototypes(object, receiver, holder,
423 scratch1, scratch2, name, miss);
424
425 // Get the value from the properties.
426 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
427 __ ret(0);
428}
429
430
431void StubCompiler::GenerateLoadCallback(JSObject* object,
432 JSObject* holder,
433 Register receiver,
434 Register name_reg,
435 Register scratch1,
436 Register scratch2,
437 AccessorInfo* callback,
438 String* name,
439 Label* miss) {
440 // Check that the receiver isn't a smi.
441 __ test(receiver, Immediate(kSmiTagMask));
442 __ j(zero, miss, not_taken);
443
444 // Check that the maps haven't changed.
445 Register reg =
446 CheckPrototypes(object, receiver, holder,
447 scratch1, scratch2, name, miss);
448
449 // Push the arguments on the JS stack of the caller.
450 __ pop(scratch2); // remove return address
451 __ push(receiver); // receiver
452 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data
453 __ push(name_reg); // name
454 __ push(reg); // holder
455 __ push(scratch2); // restore return address
456
457 // Do tail-call to the runtime system.
458 ExternalReference load_callback_property =
459 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
460 __ TailCallRuntime(load_callback_property, 4);
461}
462
463
464void StubCompiler::GenerateLoadConstant(JSObject* object,
465 JSObject* holder,
466 Register receiver,
467 Register scratch1,
468 Register scratch2,
469 Object* value,
470 String* name,
471 Label* miss) {
472 // Check that the receiver isn't a smi.
473 __ test(receiver, Immediate(kSmiTagMask));
474 __ j(zero, miss, not_taken);
475
476 // Check that the maps haven't changed.
477 Register reg =
478 CheckPrototypes(object, receiver, holder,
479 scratch1, scratch2, name, miss);
480
481 // Return the constant value.
482 __ mov(eax, Handle<Object>(value));
483 __ ret(0);
484}
485
486
487void StubCompiler::GenerateLoadInterceptor(JSObject* object,
488 JSObject* holder,
489 Smi* lookup_hint,
490 Register receiver,
491 Register name_reg,
492 Register scratch1,
493 Register scratch2,
494 String* name,
495 Label* miss) {
496 // Check that the receiver isn't a smi.
497 __ test(receiver, Immediate(kSmiTagMask));
498 __ j(zero, miss, not_taken);
499
500 // Check that the maps haven't changed.
501 Register reg =
502 CheckPrototypes(object, receiver, holder,
503 scratch1, scratch2, name, miss);
504
505 // Push the arguments on the JS stack of the caller.
506 __ pop(scratch2); // remove return address
507 __ push(receiver); // receiver
508 __ push(reg); // holder
509 __ push(name_reg); // name
510 // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
511 // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
512 __ push(Immediate(lookup_hint));
513 __ push(scratch2); // restore return address
514
515 // Do tail-call to the runtime system.
516 ExternalReference load_ic_property =
517 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
518 __ TailCallRuntime(load_ic_property, 4);
519}
520
521
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522// TODO(1241006): Avoid having lazy compile stubs specialized by the
523// number of arguments. It is not needed anymore.
524Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000526 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527
528 // Push a copy of the function onto the stack.
529 __ push(edi);
530
531 __ push(edi); // function is also the parameter to the runtime call
532 __ CallRuntime(Runtime::kLazyCompile, 1);
533 __ pop(edi);
534
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000535 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000536 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537
538 // Do a tail-call of the compiled function.
539 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
540 __ jmp(Operand(ecx));
541
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000542 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543}
544
545
546Object* CallStubCompiler::CompileCallField(Object* object,
547 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000548 int index,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000549 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550 // ----------- S t a t e -------------
551 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 Label miss;
553
554 // Get the receiver from the stack.
555 const int argc = arguments().immediate();
556 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
557
558 // Check that the receiver isn't a smi.
559 __ test(edx, Immediate(kSmiTagMask));
560 __ j(zero, &miss, not_taken);
561
562 // Do the right check and compute the holder register.
563 Register reg =
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000564 CheckPrototypes(JSObject::cast(object), edx, holder,
565 ebx, ecx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566
ager@chromium.org7c537e22008-10-16 08:43:32 +0000567 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568
569 // Check that the function really is a function.
570 __ test(edi, Immediate(kSmiTagMask));
571 __ j(zero, &miss, not_taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000572 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 __ j(not_equal, &miss, not_taken);
574
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000575 // Patch the receiver on the stack with the global proxy if
576 // necessary.
577 if (object->IsGlobalObject()) {
578 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
579 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
580 }
581
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582 // Invoke the function.
583 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
584
585 // Handle call cache miss.
586 __ bind(&miss);
587 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000588 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000589
590 // Return the generated code.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000591 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592}
593
594
595Object* CallStubCompiler::CompileCallConstant(Object* object,
596 JSObject* holder,
597 JSFunction* function,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000598 String* name,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000599 CheckType check) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600 // ----------- S t a t e -------------
601 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602 Label miss;
603
604 // Get the receiver from the stack.
605 const int argc = arguments().immediate();
606 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
607
608 // Check that the receiver isn't a smi.
609 if (check != NUMBER_CHECK) {
610 __ test(edx, Immediate(kSmiTagMask));
611 __ j(zero, &miss, not_taken);
612 }
613
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000614 // Make sure that it's okay not to patch the on stack receiver
615 // unless we're doing a receiver map check.
616 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
617
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618 switch (check) {
619 case RECEIVER_MAP_CHECK:
620 // Check that the maps haven't changed.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000621 CheckPrototypes(JSObject::cast(object), edx, holder,
622 ebx, ecx, name, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000623
624 // Patch the receiver on the stack with the global proxy if
625 // necessary.
626 if (object->IsGlobalObject()) {
627 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
628 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
629 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 break;
631
632 case STRING_CHECK:
633 // Check that the object is a two-byte string or a symbol.
634 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
635 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
636 __ cmp(ecx, FIRST_NONSTRING_TYPE);
637 __ j(above_equal, &miss, not_taken);
638 // Check that the maps starting from the prototype haven't changed.
639 GenerateLoadGlobalFunctionPrototype(masm(),
640 Context::STRING_FUNCTION_INDEX,
641 ecx);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000642 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
643 ebx, edx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644 break;
645
646 case NUMBER_CHECK: {
647 Label fast;
648 // Check that the object is a smi or a heap number.
649 __ test(edx, Immediate(kSmiTagMask));
650 __ j(zero, &fast, taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000651 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652 __ j(not_equal, &miss, not_taken);
653 __ bind(&fast);
654 // Check that the maps starting from the prototype haven't changed.
655 GenerateLoadGlobalFunctionPrototype(masm(),
656 Context::NUMBER_FUNCTION_INDEX,
657 ecx);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000658 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
659 ebx, edx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 break;
661 }
662
663 case BOOLEAN_CHECK: {
664 Label fast;
665 // Check that the object is a boolean.
666 __ cmp(edx, Factory::true_value());
667 __ j(equal, &fast, taken);
668 __ cmp(edx, Factory::false_value());
669 __ j(not_equal, &miss, not_taken);
670 __ bind(&fast);
671 // Check that the maps starting from the prototype haven't changed.
672 GenerateLoadGlobalFunctionPrototype(masm(),
673 Context::BOOLEAN_FUNCTION_INDEX,
674 ecx);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000675 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
676 ebx, edx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000677 break;
678 }
679
680 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000681 CheckPrototypes(JSObject::cast(object), edx, holder,
682 ebx, ecx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683 // Make sure object->elements()->map() != Heap::dictionary_array_map()
684 // Get the elements array of the object.
685 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
686 // Check that the object is in fast mode (not dictionary).
687 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
688 Immediate(Factory::hash_table_map()));
689 __ j(equal, &miss, not_taken);
690 break;
691
692 default:
693 UNREACHABLE();
694 }
695
696 // Get the function and setup the context.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000697 __ mov(edi, Immediate(Handle<JSFunction>(function)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000698 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
699
700 // Jump to the cached code (tail call).
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000701 ASSERT(function->is_compiled());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702 Handle<Code> code(function->code());
703 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000704 __ InvokeCode(code, expected, arguments(),
705 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000706
707 // Handle call cache miss.
708 __ bind(&miss);
709 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000710 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711
712 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000713 String* function_name = NULL;
714 if (function->shared()->name()->IsString()) {
715 function_name = String::cast(function->shared()->name());
716 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000717 return GetCode(CONSTANT_FUNCTION, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718}
719
720
721Object* CallStubCompiler::CompileCallInterceptor(Object* object,
722 JSObject* holder,
723 String* name) {
724 // ----------- S t a t e -------------
725 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000726 Label miss;
727
728 // Get the number of arguments.
729 const int argc = arguments().immediate();
730
731 // Get the receiver from the stack.
732 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000733
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734 // Check that the receiver isn't a smi.
735 __ test(edx, Immediate(kSmiTagMask));
736 __ j(zero, &miss, not_taken);
737
738 // Check that maps have not changed and compute the holder register.
739 Register reg =
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000740 CheckPrototypes(JSObject::cast(object), edx, holder,
741 ebx, ecx, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000742
743 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000744 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745
746 // Push arguments on the expression stack.
747 __ push(edx); // receiver
748 __ push(reg); // holder
749 __ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
ager@chromium.orge2902be2009-06-08 12:21:35 +0000750 __ push(Immediate(holder->InterceptorPropertyLookupHint(name)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000751
752 // Perform call.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000753 ExternalReference load_interceptor =
754 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000755 __ mov(eax, Immediate(4));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000756 __ mov(ebx, Immediate(load_interceptor));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757
758 CEntryStub stub;
759 __ CallStub(&stub);
760
761 // Move result to edi and restore receiver.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000762 __ mov(edi, eax);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000763 __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize)); // receiver
764
765 // Exit frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000766 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000767
768 // Check that the function really is a function.
769 __ test(edi, Immediate(kSmiTagMask));
770 __ j(zero, &miss, not_taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000771 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772 __ j(not_equal, &miss, not_taken);
773
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000774 // Patch the receiver on the stack with the global proxy if
775 // necessary.
776 if (object->IsGlobalObject()) {
777 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
778 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
779 }
780
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781 // Invoke the function.
782 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
783
784 // Handle load cache miss.
785 __ bind(&miss);
786 Handle<Code> ic = ComputeCallMiss(argc);
ager@chromium.org236ad962008-09-25 09:45:57 +0000787 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788
789 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000790 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791}
792
793
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000794Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
795 GlobalObject* holder,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000796 JSGlobalPropertyCell* cell,
797 JSFunction* function,
798 String* name) {
799 // ----------- S t a t e -------------
800 // -----------------------------------
801 Label miss;
802
803 __ IncrementCounter(&Counters::call_global_inline, 1);
804
805 // Get the number of arguments.
806 const int argc = arguments().immediate();
807
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000808 // Get the receiver from the stack.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000809 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000810
811 // If the object is the holder then we know that it's a global
812 // object which can only happen for contextual calls. In this case,
813 // the receiver cannot be a smi.
814 if (object != holder) {
815 __ test(edx, Immediate(kSmiTagMask));
816 __ j(zero, &miss, not_taken);
817 }
818
819 // Check that the maps haven't changed.
820 CheckPrototypes(object, edx, holder, ebx, ecx, name, &miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000821
822 // Get the value from the cell.
823 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
824 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
825
826 // Check that the cell contains the same function.
827 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
828 __ j(not_equal, &miss, not_taken);
829
830 // Patch the receiver on the stack with the global proxy.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000831 if (object->IsGlobalObject()) {
832 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
833 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
834 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000835
836 // Setup the context (function already in edi).
837 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
838
839 // Jump to the cached code (tail call).
840 ASSERT(function->is_compiled());
841 Handle<Code> code(function->code());
842 ParameterCount expected(function->shared()->formal_parameter_count());
843 __ InvokeCode(code, expected, arguments(),
844 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
845
846 // Handle call cache miss.
847 __ bind(&miss);
848 __ DecrementCounter(&Counters::call_global_inline, 1);
849 __ IncrementCounter(&Counters::call_global_inline_miss, 1);
850 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
851 __ jmp(ic, RelocInfo::CODE_TARGET);
852
853 // Return the generated code.
854 return GetCode(NORMAL, name);
855}
856
857
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000858Object* StoreStubCompiler::CompileStoreField(JSObject* object,
859 int index,
860 Map* transition,
861 String* name) {
862 // ----------- S t a t e -------------
863 // -- eax : value
864 // -- ecx : name
865 // -- esp[0] : return address
866 // -- esp[4] : receiver
867 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000868 Label miss;
869
870 // Get the object from the stack.
871 __ mov(ebx, Operand(esp, 1 * kPointerSize));
872
873 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000874 GenerateStoreField(masm(),
875 Builtins::StoreIC_ExtendStorage,
876 object,
877 index,
878 transition,
879 ebx, ecx, edx,
880 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000881
882 // Handle store cache miss.
883 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000884 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000886 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887
888 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000889 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890}
891
892
893Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
894 AccessorInfo* callback,
895 String* name) {
896 // ----------- S t a t e -------------
897 // -- eax : value
898 // -- ecx : name
899 // -- esp[0] : return address
900 // -- esp[4] : receiver
901 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000902 Label miss;
903
904 // Get the object from the stack.
905 __ mov(ebx, Operand(esp, 1 * kPointerSize));
906
907 // Check that the object isn't a smi.
908 __ test(ebx, Immediate(kSmiTagMask));
909 __ j(zero, &miss, not_taken);
910
911 // Check that the map of the object hasn't changed.
912 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
913 Immediate(Handle<Map>(object->map())));
914 __ j(not_equal, &miss, not_taken);
915
916 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000917 if (object->IsJSGlobalProxy()) {
918 __ CheckAccessGlobalProxy(ebx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919 }
920
921 // Stub never generated for non-global objects that require access
922 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000923 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000924
925 __ pop(ebx); // remove the return address
926 __ push(Operand(esp, 0)); // receiver
927 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info
928 __ push(ecx); // name
929 __ push(eax); // value
930 __ push(ebx); // restore return address
931
mads.s.ager31e71382008-08-13 09:32:07 +0000932 // Do tail-call to the runtime system.
933 ExternalReference store_callback_property =
934 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
935 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936
937 // Handle store cache miss.
938 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000939 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000940 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000941 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942
943 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000944 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945}
946
947
948Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
949 String* name) {
950 // ----------- S t a t e -------------
951 // -- eax : value
952 // -- ecx : name
953 // -- esp[0] : return address
954 // -- esp[4] : receiver
955 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000956 Label miss;
957
958 // Get the object from the stack.
959 __ mov(ebx, Operand(esp, 1 * kPointerSize));
960
961 // Check that the object isn't a smi.
962 __ test(ebx, Immediate(kSmiTagMask));
963 __ j(zero, &miss, not_taken);
964
965 // Check that the map of the object hasn't changed.
966 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
967 Immediate(Handle<Map>(receiver->map())));
968 __ j(not_equal, &miss, not_taken);
969
970 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000971 if (receiver->IsJSGlobalProxy()) {
972 __ CheckAccessGlobalProxy(ebx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973 }
974
975 // Stub never generated for non-global objects that require access
976 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000977 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000978
979 __ pop(ebx); // remove the return address
980 __ push(Operand(esp, 0)); // receiver
981 __ push(ecx); // name
982 __ push(eax); // value
983 __ push(ebx); // restore return address
984
mads.s.ager31e71382008-08-13 09:32:07 +0000985 // Do tail-call to the runtime system.
986 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000987 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000988 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000989
990 // Handle store cache miss.
991 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000992 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000993 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000994 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995
996 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000997 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000998}
999
1000
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001001Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
1002 JSGlobalPropertyCell* cell,
1003 String* name) {
1004 // ----------- S t a t e -------------
1005 // -- eax : value
1006 // -- ecx : name
1007 // -- esp[0] : return address
1008 // -- esp[4] : receiver
1009 // -----------------------------------
1010 Label miss;
1011
1012 __ IncrementCounter(&Counters::named_store_global_inline, 1);
1013
1014 // Check that the map of the global has not changed.
1015 __ mov(ebx, (Operand(esp, kPointerSize)));
1016 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1017 Immediate(Handle<Map>(object->map())));
1018 __ j(not_equal, &miss, not_taken);
1019
1020 // Store the value in the cell.
1021 __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1022 __ mov(FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset), eax);
1023
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001024 // Return the value (register eax).
1025 __ ret(0);
1026
1027 // Handle store cache miss.
1028 __ bind(&miss);
1029 __ DecrementCounter(&Counters::named_store_global_inline, 1);
1030 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
1031 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1032 __ jmp(ic, RelocInfo::CODE_TARGET);
1033
1034 // Return the generated code.
1035 return GetCode(NORMAL, name);
1036}
1037
1038
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001039Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1040 int index,
1041 Map* transition,
1042 String* name) {
1043 // ----------- S t a t e -------------
1044 // -- eax : value
1045 // -- esp[0] : return address
1046 // -- esp[4] : key
1047 // -- esp[8] : receiver
1048 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049 Label miss;
1050
1051 __ IncrementCounter(&Counters::keyed_store_field, 1);
1052
1053 // Get the name from the stack.
1054 __ mov(ecx, Operand(esp, 1 * kPointerSize));
1055 // Check that the name has not changed.
1056 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
1057 __ j(not_equal, &miss, not_taken);
1058
1059 // Get the object from the stack.
1060 __ mov(ebx, Operand(esp, 2 * kPointerSize));
1061
1062 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +00001063 GenerateStoreField(masm(),
1064 Builtins::KeyedStoreIC_ExtendStorage,
1065 object,
1066 index,
1067 transition,
1068 ebx, ecx, edx,
1069 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001070
1071 // Handle store cache miss.
1072 __ bind(&miss);
1073 __ DecrementCounter(&Counters::keyed_store_field, 1);
1074 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +00001075 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001076
1077 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001078 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001079}
1080
1081
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001082
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1084 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001085 int index,
1086 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001087 // ----------- S t a t e -------------
1088 // -- ecx : name
1089 // -- esp[0] : return address
1090 // -- esp[4] : receiver
1091 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001092 Label miss;
1093
1094 __ mov(eax, (Operand(esp, kPointerSize)));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001095 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001096 __ bind(&miss);
1097 GenerateLoadMiss(masm(), Code::LOAD_IC);
1098
1099 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001100 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101}
1102
1103
1104Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
1105 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001106 AccessorInfo* callback,
1107 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001108 // ----------- S t a t e -------------
1109 // -- ecx : name
1110 // -- esp[0] : return address
1111 // -- esp[4] : receiver
1112 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113 Label miss;
1114
1115 __ mov(eax, (Operand(esp, kPointerSize)));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001116 GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
1117 callback, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001118 __ bind(&miss);
1119 GenerateLoadMiss(masm(), Code::LOAD_IC);
1120
1121 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001122 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123}
1124
1125
1126Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1127 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001128 Object* value,
1129 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130 // ----------- S t a t e -------------
1131 // -- ecx : name
1132 // -- esp[0] : return address
1133 // -- esp[4] : receiver
1134 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135 Label miss;
1136
1137 __ mov(eax, (Operand(esp, kPointerSize)));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001138 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139 __ bind(&miss);
1140 GenerateLoadMiss(masm(), Code::LOAD_IC);
1141
1142 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001143 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001144}
1145
1146
1147Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1148 JSObject* holder,
1149 String* name) {
1150 // ----------- S t a t e -------------
1151 // -- ecx : name
1152 // -- esp[0] : return address
1153 // -- esp[4] : receiver
1154 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001155 Label miss;
1156
1157 __ mov(eax, (Operand(esp, kPointerSize)));
ager@chromium.orge2902be2009-06-08 12:21:35 +00001158 // TODO(368): Compile in the whole chain: all the interceptors in
1159 // prototypes and ultimate answer.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001160 GenerateLoadInterceptor(receiver,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001161 holder,
1162 holder->InterceptorPropertyLookupHint(name),
1163 eax,
1164 ecx,
1165 edx,
1166 ebx,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001167 name,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001168 &miss);
1169
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001170 __ bind(&miss);
1171 GenerateLoadMiss(masm(), Code::LOAD_IC);
1172
1173 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001174 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001175}
1176
1177
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001178Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1179 GlobalObject* holder,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001180 JSGlobalPropertyCell* cell,
1181 String* name,
1182 bool is_dont_delete) {
1183 // ----------- S t a t e -------------
1184 // -- ecx : name
1185 // -- esp[0] : return address
1186 // -- esp[4] : receiver
1187 // -----------------------------------
1188 Label miss;
1189
1190 __ IncrementCounter(&Counters::named_load_global_inline, 1);
1191
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001192 // Get the receiver from the stack.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001193 __ mov(eax, (Operand(esp, kPointerSize)));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001194
1195 // If the object is the holder then we know that it's a global
1196 // object which can only happen for contextual loads. In this case,
1197 // the receiver cannot be a smi.
1198 if (object != holder) {
1199 __ test(eax, Immediate(kSmiTagMask));
1200 __ j(zero, &miss, not_taken);
1201 }
1202
1203 // Check that the maps haven't changed.
1204 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001205
1206 // Get the value from the cell.
1207 __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1208 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
1209
1210 // Check for deleted property if property can actually be deleted.
1211 if (!is_dont_delete) {
1212 __ cmp(eax, Factory::the_hole_value());
1213 __ j(equal, &miss, not_taken);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001214 } else if (FLAG_debug_code) {
1215 __ cmp(eax, Factory::the_hole_value());
1216 __ Check(not_equal, "DontDelete cells can't contain the hole");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001217 }
1218
1219 __ ret(0);
1220
1221 __ bind(&miss);
1222 __ DecrementCounter(&Counters::named_load_global_inline, 1);
1223 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
1224 GenerateLoadMiss(masm(), Code::LOAD_IC);
1225
1226 // Return the generated code.
1227 return GetCode(NORMAL, name);
1228}
1229
1230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001231Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
1232 JSObject* receiver,
1233 JSObject* holder,
1234 int index) {
1235 // ----------- S t a t e -------------
1236 // -- esp[0] : return address
1237 // -- esp[4] : name
1238 // -- esp[8] : receiver
1239 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240 Label miss;
1241
1242 __ mov(eax, (Operand(esp, kPointerSize)));
1243 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1244 __ IncrementCounter(&Counters::keyed_load_field, 1);
1245
1246 // Check that the name has not changed.
1247 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1248 __ j(not_equal, &miss, not_taken);
1249
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001250 GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss);
1251
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252 __ bind(&miss);
1253 __ DecrementCounter(&Counters::keyed_load_field, 1);
1254 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1255
1256 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001257 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001258}
1259
1260
1261Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1262 JSObject* receiver,
1263 JSObject* holder,
1264 AccessorInfo* callback) {
1265 // ----------- S t a t e -------------
1266 // -- esp[0] : return address
1267 // -- esp[4] : name
1268 // -- esp[8] : receiver
1269 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 Label miss;
1271
1272 __ mov(eax, (Operand(esp, kPointerSize)));
1273 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1274 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1275
1276 // Check that the name has not changed.
1277 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1278 __ j(not_equal, &miss, not_taken);
1279
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001280 GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx,
1281 callback, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282 __ bind(&miss);
1283 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1284 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1285
1286 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001287 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001288}
1289
1290
1291Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1292 JSObject* receiver,
1293 JSObject* holder,
1294 Object* value) {
1295 // ----------- S t a t e -------------
1296 // -- esp[0] : return address
1297 // -- esp[4] : name
1298 // -- esp[8] : receiver
1299 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 Label miss;
1301
1302 __ mov(eax, (Operand(esp, kPointerSize)));
1303 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1304 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1305
1306 // Check that the name has not changed.
1307 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1308 __ j(not_equal, &miss, not_taken);
1309
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001310 GenerateLoadConstant(receiver, holder, ecx, ebx, edx,
1311 value, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001312 __ bind(&miss);
1313 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1314 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1315
1316 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001317 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001318}
1319
1320
1321Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1322 JSObject* holder,
1323 String* name) {
1324 // ----------- S t a t e -------------
1325 // -- esp[0] : return address
1326 // -- esp[4] : name
1327 // -- esp[8] : receiver
1328 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 Label miss;
1330
1331 __ mov(eax, (Operand(esp, kPointerSize)));
1332 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1333 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1334
1335 // Check that the name has not changed.
1336 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1337 __ j(not_equal, &miss, not_taken);
1338
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001339 GenerateLoadInterceptor(receiver,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001340 holder,
1341 Smi::FromInt(JSObject::kLookupInHolder),
1342 ecx,
1343 eax,
1344 edx,
1345 ebx,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001346 name,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001347 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348 __ bind(&miss);
1349 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1350 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1351
1352 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001353 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354}
1355
1356
1357
1358
1359Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1360 // ----------- S t a t e -------------
1361 // -- esp[0] : return address
1362 // -- esp[4] : name
1363 // -- esp[8] : receiver
1364 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365 Label miss;
1366
1367 __ mov(eax, (Operand(esp, kPointerSize)));
1368 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1369 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1370
1371 // Check that the name has not changed.
1372 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1373 __ j(not_equal, &miss, not_taken);
1374
1375 GenerateLoadArrayLength(masm(), ecx, edx, &miss);
1376 __ bind(&miss);
1377 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1378 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1379
1380 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001381 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001382}
1383
1384
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001385Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001386 // ----------- S t a t e -------------
1387 // -- esp[0] : return address
1388 // -- esp[4] : name
1389 // -- esp[8] : receiver
1390 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001391 Label miss;
1392
1393 __ mov(eax, (Operand(esp, kPointerSize)));
1394 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1395 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1396
1397 // Check that the name has not changed.
1398 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1399 __ j(not_equal, &miss, not_taken);
1400
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001401 GenerateLoadStringLength(masm(), ecx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001402 __ bind(&miss);
1403 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1404 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1405
1406 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001407 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001408}
1409
1410
1411Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1412 // ----------- S t a t e -------------
1413 // -- esp[0] : return address
1414 // -- esp[4] : name
1415 // -- esp[8] : receiver
1416 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417 Label miss;
1418
1419 __ mov(eax, (Operand(esp, kPointerSize)));
1420 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1421 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1422
1423 // Check that the name has not changed.
1424 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1425 __ j(not_equal, &miss, not_taken);
1426
1427 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
1428 __ bind(&miss);
1429 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1430 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1431
1432 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001433 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001434}
1435
1436
1437#undef __
1438
1439} } // namespace v8::internal