blob: 01526dac89c7a6cd560ad55806d0a959a577eca2 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 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
34namespace v8 { namespace internal {
35
36#define __ masm->
37
38
39static void ProbeTable(MacroAssembler* masm,
40 Code::Flags flags,
41 StubCache::Table table,
42 Register name,
43 Register offset) {
44 ExternalReference key_offset(SCTableReference::keyReference(table));
45 ExternalReference value_offset(SCTableReference::valueReference(table));
46
47 Label miss;
48
49 // Save the offset on the stack.
50 __ push(offset);
51
52 // Check that the key in the entry matches the name.
53 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
54 __ j(not_equal, &miss, not_taken);
55
56 // Get the code entry from the cache.
57 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
58
59 // Check that the flags match what we're looking for.
60 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
61 __ and_(offset, ~Code::kFlagsTypeMask);
62 __ cmp(offset, flags);
63 __ j(not_equal, &miss);
64
65 // Restore offset and re-load code entry from cache.
66 __ pop(offset);
67 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
68
69 // Jump to the first instruction in the code stub.
70 __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
71 __ jmp(Operand(offset));
72
73 // Miss: Restore offset and fall through.
74 __ bind(&miss);
75 __ pop(offset);
76}
77
78
79void StubCache::GenerateProbe(MacroAssembler* masm,
80 Code::Flags flags,
81 Register receiver,
82 Register name,
83 Register scratch) {
84 Label miss;
85
86 // Make sure that code is valid. The shifting code relies on the
87 // entry size being 8.
88 ASSERT(sizeof(Entry) == 8);
89
90 // Make sure the flags does not name a specific type.
91 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
92
93 // Make sure that there are no register conflicts.
94 ASSERT(!scratch.is(receiver));
95 ASSERT(!scratch.is(name));
96
97 // Check that the receiver isn't a smi.
98 __ test(receiver, Immediate(kSmiTagMask));
99 __ j(zero, &miss, not_taken);
100
101 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000102 __ mov(scratch, FieldOperand(name, String::kLengthOffset));
103 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 __ xor_(scratch, flags);
105 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
106
107 // Probe the primary table.
108 ProbeTable(masm, flags, kPrimary, name, scratch);
109
110 // Primary miss: Compute hash for secondary probe.
111 __ sub(scratch, Operand(name));
112 __ add(Operand(scratch), Immediate(flags));
113 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
114
115 // Probe the secondary table.
116 ProbeTable(masm, flags, kSecondary, name, scratch);
117
118 // Cache miss: Fall-through and let caller handle the miss by
119 // entering the runtime system.
120 __ bind(&miss);
121}
122
123
124void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
125 int index,
126 Register prototype) {
127 // Load the global or builtins object from the current context.
128 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
129 // Load the global context from the global or builtins object.
130 __ mov(prototype,
131 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
132 // Load the function from the global context.
133 __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
134 // Load the initial map. The global functions all have initial maps.
135 __ mov(prototype,
136 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
137 // Load the prototype from the initial map.
138 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
139}
140
141
142void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
143 Register receiver,
144 Register scratch,
145 Label* miss_label) {
146 // Check that the receiver isn't a smi.
147 __ test(receiver, Immediate(kSmiTagMask));
148 __ j(zero, miss_label, not_taken);
149
150 // Check that the object is a JS array.
151 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
152 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
153 __ cmp(scratch, JS_ARRAY_TYPE);
154 __ j(not_equal, miss_label, not_taken);
155
156 // Load length directly from the JS array.
157 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
158 __ ret(0);
159}
160
161
162void StubCompiler::GenerateLoadShortStringLength(MacroAssembler* masm,
163 Register receiver,
164 Register scratch,
165 Label* miss_label) {
166 // Check that the receiver isn't a smi.
167 __ test(receiver, Immediate(kSmiTagMask));
168 __ j(zero, miss_label, not_taken);
169
170 // Check that the object is a short string.
171 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
172 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
173 __ and_(scratch, kIsNotStringMask | kStringSizeMask);
174 __ cmp(scratch, kStringTag | kShortStringTag);
175 __ j(not_equal, miss_label, not_taken);
176
177 // Load length directly from the string.
178 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
179 __ shr(eax, String::kShortLengthShift);
180 __ shl(eax, kSmiTagSize);
181 __ ret(0);
182}
183
184void StubCompiler::GenerateLoadMediumStringLength(MacroAssembler* masm,
185 Register receiver,
186 Register scratch,
187 Label* miss_label) {
188 // Check that the receiver isn't a smi.
189 __ test(receiver, Immediate(kSmiTagMask));
190 __ j(zero, miss_label, not_taken);
191
192 // Check that the object is a short string.
193 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
194 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
195 __ and_(scratch, kIsNotStringMask | kStringSizeMask);
196 __ cmp(scratch, kStringTag | kMediumStringTag);
197 __ j(not_equal, miss_label, not_taken);
198
199 // Load length directly from the string.
200 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
201 __ shr(eax, String::kMediumLengthShift);
202 __ shl(eax, kSmiTagSize);
203 __ ret(0);
204}
205
206
207void StubCompiler::GenerateLoadLongStringLength(MacroAssembler* masm,
208 Register receiver,
209 Register scratch,
210 Label* miss_label) {
211 // Check that the receiver isn't a smi.
212 __ test(receiver, Immediate(kSmiTagMask));
213 __ j(zero, miss_label, not_taken);
214
215 // Check that the object is a short string.
216 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
217 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
218 __ and_(scratch, kIsNotStringMask | kStringSizeMask);
219 __ cmp(scratch, kStringTag | kLongStringTag);
220 __ j(not_equal, miss_label, not_taken);
221
222 // Load length directly from the string.
223 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
224 __ shr(eax, String::kLongLengthShift);
225 __ shl(eax, kSmiTagSize);
226 __ ret(0);
227}
228
229
230void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
231 Register receiver,
232 Register scratch1,
233 Register scratch2,
234 Label* miss_label) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000235 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236 __ mov(eax, Operand(scratch1));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000237 __ ret(0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000238}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239
ager@chromium.org7c537e22008-10-16 08:43:32 +0000240
241// Load a fast property out of a holder object (src). In-object properties
242// are loaded directly otherwise the property is loaded from the properties
243// fixed array.
244void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
245 Register dst, Register src,
246 JSObject* holder, int index) {
247 // Adjust for the number of properties stored in the holder.
248 index -= holder->map()->inobject_properties();
249 if (index < 0) {
250 // Get the property straight out of the holder.
251 int offset = holder->map()->instance_size() + (index * kPointerSize);
252 __ mov(dst, FieldOperand(src, offset));
253 } else {
254 // Calculate the offset into the properties array.
255 int offset = index * kPointerSize + Array::kHeaderSize;
256 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
257 __ mov(dst, FieldOperand(dst, offset));
258 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259}
260
261
262void StubCompiler::GenerateLoadField(MacroAssembler* masm,
263 JSObject* object,
264 JSObject* holder,
265 Register receiver,
266 Register scratch1,
267 Register scratch2,
268 int index,
269 Label* miss_label) {
270 // Check that the receiver isn't a smi.
271 __ test(receiver, Immediate(kSmiTagMask));
272 __ j(zero, miss_label, not_taken);
273
274 // Check that the maps haven't changed.
275 Register reg =
276 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
277
ager@chromium.org7c537e22008-10-16 08:43:32 +0000278 // Get the value from the properties.
279 GenerateFastPropertyLoad(masm, eax, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000280 __ ret(0);
281}
282
283
284void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
285 JSObject* object,
286 JSObject* holder,
287 Register receiver,
288 Register name,
289 Register scratch1,
290 Register scratch2,
291 AccessorInfo* callback,
292 Label* miss_label) {
293 // Check that the receiver isn't a smi.
294 __ test(receiver, Immediate(kSmiTagMask));
295 __ j(zero, miss_label, not_taken);
296
297 // Check that the maps haven't changed.
298 Register reg =
299 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
300
301 // Push the arguments on the JS stack of the caller.
302 __ pop(scratch2); // remove return address
303 __ push(receiver); // receiver
304 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data
305 __ push(name); // name
306 __ push(reg); // holder
307 __ push(scratch2); // restore return address
308
mads.s.ager31e71382008-08-13 09:32:07 +0000309 // Do tail-call to the runtime system.
310 ExternalReference load_callback_property =
311 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
312 __ TailCallRuntime(load_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313}
314
315
316void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
317 JSObject* object,
318 JSObject* holder,
319 Register receiver,
320 Register scratch1,
321 Register scratch2,
322 Object* value,
323 Label* miss_label) {
324 // Check that the receiver isn't a smi.
325 __ test(receiver, Immediate(kSmiTagMask));
326 __ j(zero, miss_label, not_taken);
327
328 // Check that the maps haven't changed.
329 Register reg =
330 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
331
332 // Return the constant value.
333 __ mov(eax, Handle<Object>(value));
334 __ ret(0);
335}
336
337
338void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
339 JSObject* object,
340 JSObject* holder,
341 Register receiver,
342 Register name,
343 Register scratch1,
344 Register scratch2,
345 Label* miss_label) {
346 // Check that the receiver isn't a smi.
347 __ test(receiver, Immediate(kSmiTagMask));
348 __ j(zero, miss_label, not_taken);
349
350 // Check that the maps haven't changed.
351 Register reg =
352 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
353
354 // Push the arguments on the JS stack of the caller.
355 __ pop(scratch2); // remove return address
356 __ push(receiver); // receiver
357 __ push(reg); // holder
358 __ push(name); // name
359 __ push(scratch2); // restore return address
360
mads.s.ager31e71382008-08-13 09:32:07 +0000361 // Do tail-call to the runtime system.
362 ExternalReference load_ic_property =
363 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
364 __ TailCallRuntime(load_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365}
366
367
368void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
369 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
370 Code* code = NULL;
371 if (kind == Code::LOAD_IC) {
372 code = Builtins::builtin(Builtins::LoadIC_Miss);
373 } else {
374 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
375 }
376
377 Handle<Code> ic(code);
ager@chromium.org236ad962008-09-25 09:45:57 +0000378 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000379}
380
381
382void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000383 Builtins::Name storage_extend,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384 JSObject* object,
385 int index,
386 Map* transition,
387 Register receiver_reg,
388 Register name_reg,
389 Register scratch,
390 Label* miss_label) {
391 // Check that the object isn't a smi.
392 __ test(receiver_reg, Immediate(kSmiTagMask));
393 __ j(zero, miss_label, not_taken);
394
395 // Check that the map of the object hasn't changed.
396 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
397 Immediate(Handle<Map>(object->map())));
398 __ j(not_equal, miss_label, not_taken);
399
400 // Perform global security token check if needed.
401 if (object->IsJSGlobalObject()) {
402 __ CheckAccessGlobal(receiver_reg, scratch, miss_label);
403 }
404
405 // Stub never generated for non-global objects that require access
406 // checks.
407 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
408
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000409 // Perform map transition for the receiver if necessary.
410 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
411 // The properties must be extended before we can store the value.
412 // We jump to a runtime call that extends the propeties array.
413 __ mov(Operand(ecx), Immediate(Handle<Map>(transition)));
414 Handle<Code> ic(Builtins::builtin(storage_extend));
415 __ jmp(ic, RelocInfo::CODE_TARGET);
416 return;
417 }
418
ager@chromium.org7c537e22008-10-16 08:43:32 +0000419 // Adjust for the number of properties stored in the object. Even in the
420 // face of a transition we can use the old map here because the size of the
421 // object and the number of in-object properties is not going to change.
422 index -= object->map()->inobject_properties();
423
424 if (index >= 0) {
425 // Get the properties array (optimistically).
426 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
427 }
428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429 if (transition != NULL) {
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000430 // Update the map of the object; no write barrier updating is
431 // needed because the map is never in new space.
432 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
433 Immediate(Handle<Map>(transition)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000434 }
435
ager@chromium.org7c537e22008-10-16 08:43:32 +0000436 if (index < 0) {
437 // Set the property straight into the object.
438 int offset = object->map()->instance_size() + (index * kPointerSize);
439 __ mov(FieldOperand(receiver_reg, offset), eax);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000440
ager@chromium.org7c537e22008-10-16 08:43:32 +0000441 // Update the write barrier for the array address.
442 // Pass the value being stored in the now unused name_reg.
443 __ mov(name_reg, Operand(eax));
444 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
445 } else {
446 // Write to the properties array.
447 int offset = index * kPointerSize + Array::kHeaderSize;
448 __ mov(FieldOperand(scratch, offset), eax);
449
450 // Update the write barrier for the array address.
451 // Pass the value being stored in the now unused name_reg.
452 __ mov(name_reg, Operand(eax));
453 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
454 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455
456 // Return the value (register eax).
457 __ ret(0);
458}
459
460
461#undef __
462
463#define __ masm()->
464
465
466// TODO(1241006): Avoid having lazy compile stubs specialized by the
467// number of arguments. It is not needed anymore.
468Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
469 HandleScope scope;
470
471 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000472 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473
474 // Push a copy of the function onto the stack.
475 __ push(edi);
476
477 __ push(edi); // function is also the parameter to the runtime call
478 __ CallRuntime(Runtime::kLazyCompile, 1);
479 __ pop(edi);
480
ager@chromium.org236ad962008-09-25 09:45:57 +0000481 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482
483 // Do a tail-call of the compiled function.
484 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
485 __ jmp(Operand(ecx));
486
487 return GetCodeWithFlags(flags);
488}
489
490
491Object* CallStubCompiler::CompileCallField(Object* object,
492 JSObject* holder,
493 int index) {
494 // ----------- S t a t e -------------
495 // -----------------------------------
496
497 HandleScope scope;
498 Label miss;
499
500 // Get the receiver from the stack.
501 const int argc = arguments().immediate();
502 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
503
504 // Check that the receiver isn't a smi.
505 __ test(edx, Immediate(kSmiTagMask));
506 __ j(zero, &miss, not_taken);
507
508 // Do the right check and compute the holder register.
509 Register reg =
510 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
511
ager@chromium.org7c537e22008-10-16 08:43:32 +0000512 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513
514 // Check that the function really is a function.
515 __ test(edi, Immediate(kSmiTagMask));
516 __ j(zero, &miss, not_taken);
517 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset)); // get the map
518 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
519 __ cmp(ebx, JS_FUNCTION_TYPE);
520 __ j(not_equal, &miss, not_taken);
521
522 // Invoke the function.
523 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
524
525 // Handle call cache miss.
526 __ bind(&miss);
527 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000528 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529
530 // Return the generated code.
531 return GetCode(FIELD);
532}
533
534
535Object* CallStubCompiler::CompileCallConstant(Object* object,
536 JSObject* holder,
537 JSFunction* function,
538 CheckType check) {
539 // ----------- S t a t e -------------
540 // -----------------------------------
541
542 HandleScope scope;
543 Label miss;
544
545 // Get the receiver from the stack.
546 const int argc = arguments().immediate();
547 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
548
549 // Check that the receiver isn't a smi.
550 if (check != NUMBER_CHECK) {
551 __ test(edx, Immediate(kSmiTagMask));
552 __ j(zero, &miss, not_taken);
553 }
554
555 switch (check) {
556 case RECEIVER_MAP_CHECK:
557 // Check that the maps haven't changed.
558 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
559 break;
560
561 case STRING_CHECK:
562 // Check that the object is a two-byte string or a symbol.
563 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
564 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
565 __ cmp(ecx, FIRST_NONSTRING_TYPE);
566 __ j(above_equal, &miss, not_taken);
567 // Check that the maps starting from the prototype haven't changed.
568 GenerateLoadGlobalFunctionPrototype(masm(),
569 Context::STRING_FUNCTION_INDEX,
570 ecx);
571 __ CheckMaps(JSObject::cast(object->GetPrototype()),
572 ecx, holder, ebx, edx, &miss);
573 break;
574
575 case NUMBER_CHECK: {
576 Label fast;
577 // Check that the object is a smi or a heap number.
578 __ test(edx, Immediate(kSmiTagMask));
579 __ j(zero, &fast, taken);
580 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
581 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
582 __ cmp(ecx, HEAP_NUMBER_TYPE);
583 __ j(not_equal, &miss, not_taken);
584 __ bind(&fast);
585 // Check that the maps starting from the prototype haven't changed.
586 GenerateLoadGlobalFunctionPrototype(masm(),
587 Context::NUMBER_FUNCTION_INDEX,
588 ecx);
589 __ CheckMaps(JSObject::cast(object->GetPrototype()),
590 ecx, holder, ebx, edx, &miss);
591 break;
592 }
593
594 case BOOLEAN_CHECK: {
595 Label fast;
596 // Check that the object is a boolean.
597 __ cmp(edx, Factory::true_value());
598 __ j(equal, &fast, taken);
599 __ cmp(edx, Factory::false_value());
600 __ j(not_equal, &miss, not_taken);
601 __ bind(&fast);
602 // Check that the maps starting from the prototype haven't changed.
603 GenerateLoadGlobalFunctionPrototype(masm(),
604 Context::BOOLEAN_FUNCTION_INDEX,
605 ecx);
606 __ CheckMaps(JSObject::cast(object->GetPrototype()),
607 ecx, holder, ebx, edx, &miss);
608 break;
609 }
610
611 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
612 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
613 // Make sure object->elements()->map() != Heap::dictionary_array_map()
614 // Get the elements array of the object.
615 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
616 // Check that the object is in fast mode (not dictionary).
617 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
618 Immediate(Factory::hash_table_map()));
619 __ j(equal, &miss, not_taken);
620 break;
621
622 default:
623 UNREACHABLE();
624 }
625
626 // Get the function and setup the context.
627 __ mov(Operand(edi), Immediate(Handle<JSFunction>(function)));
628 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
629
630 // Jump to the cached code (tail call).
631 Handle<Code> code(function->code());
632 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000633 __ InvokeCode(code, expected, arguments(),
634 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000635
636 // Handle call cache miss.
637 __ bind(&miss);
638 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000639 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000640
641 // Return the generated code.
642 return GetCode(CONSTANT_FUNCTION);
643}
644
645
646Object* CallStubCompiler::CompileCallInterceptor(Object* object,
647 JSObject* holder,
648 String* name) {
649 // ----------- S t a t e -------------
650 // -----------------------------------
651
652 HandleScope scope;
653 Label miss;
654
655 // Get the number of arguments.
656 const int argc = arguments().immediate();
657
658 // Get the receiver from the stack.
659 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
660 // Check that the receiver isn't a smi.
661 __ test(edx, Immediate(kSmiTagMask));
662 __ j(zero, &miss, not_taken);
663
664 // Check that maps have not changed and compute the holder register.
665 Register reg =
666 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
667
668 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000669 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670
671 // Push arguments on the expression stack.
672 __ push(edx); // receiver
673 __ push(reg); // holder
674 __ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
675
676 // Perform call.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000677 ExternalReference load_interceptor =
678 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000679 __ mov(Operand(eax), Immediate(3));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000680 __ mov(Operand(ebx), Immediate(load_interceptor));
681
682 CEntryStub stub;
683 __ CallStub(&stub);
684
685 // Move result to edi and restore receiver.
686 __ mov(Operand(edi), eax);
687 __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize)); // receiver
688
689 // Exit frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000690 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691
692 // Check that the function really is a function.
693 __ test(edi, Immediate(kSmiTagMask));
694 __ j(zero, &miss, not_taken);
695 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
696 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
697 __ cmp(ebx, JS_FUNCTION_TYPE);
698 __ j(not_equal, &miss, not_taken);
699
700 // Invoke the function.
701 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
702
703 // Handle load cache miss.
704 __ bind(&miss);
705 Handle<Code> ic = ComputeCallMiss(argc);
ager@chromium.org236ad962008-09-25 09:45:57 +0000706 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707
708 // Return the generated code.
709 return GetCode(INTERCEPTOR);
710}
711
712
713Object* StoreStubCompiler::CompileStoreField(JSObject* object,
714 int index,
715 Map* transition,
716 String* name) {
717 // ----------- S t a t e -------------
718 // -- eax : value
719 // -- ecx : name
720 // -- esp[0] : return address
721 // -- esp[4] : receiver
722 // -----------------------------------
723
724 HandleScope scope;
725 Label miss;
726
727 // Get the object from the stack.
728 __ mov(ebx, Operand(esp, 1 * kPointerSize));
729
730 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000731 GenerateStoreField(masm(),
732 Builtins::StoreIC_ExtendStorage,
733 object,
734 index,
735 transition,
736 ebx, ecx, edx,
737 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000738
739 // Handle store cache miss.
740 __ bind(&miss);
741 __ mov(Operand(ecx), Immediate(Handle<String>(name))); // restore name
742 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000743 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000744
745 // Return the generated code.
746 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
747}
748
749
750Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
751 AccessorInfo* callback,
752 String* name) {
753 // ----------- S t a t e -------------
754 // -- eax : value
755 // -- ecx : name
756 // -- esp[0] : return address
757 // -- esp[4] : receiver
758 // -----------------------------------
759
760 HandleScope scope;
761 Label miss;
762
763 // Get the object from the stack.
764 __ mov(ebx, Operand(esp, 1 * kPointerSize));
765
766 // Check that the object isn't a smi.
767 __ test(ebx, Immediate(kSmiTagMask));
768 __ j(zero, &miss, not_taken);
769
770 // Check that the map of the object hasn't changed.
771 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
772 Immediate(Handle<Map>(object->map())));
773 __ j(not_equal, &miss, not_taken);
774
775 // Perform global security token check if needed.
776 if (object->IsJSGlobalObject()) {
777 __ CheckAccessGlobal(ebx, edx, &miss);
778 }
779
780 // Stub never generated for non-global objects that require access
781 // checks.
782 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
783
784 __ pop(ebx); // remove the return address
785 __ push(Operand(esp, 0)); // receiver
786 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info
787 __ push(ecx); // name
788 __ push(eax); // value
789 __ push(ebx); // restore return address
790
mads.s.ager31e71382008-08-13 09:32:07 +0000791 // Do tail-call to the runtime system.
792 ExternalReference store_callback_property =
793 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
794 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000795
796 // Handle store cache miss.
797 __ bind(&miss);
798 __ mov(Operand(ecx), Immediate(Handle<String>(name))); // restore name
799 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000800 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000801
802 // Return the generated code.
803 return GetCode(CALLBACKS);
804}
805
806
807Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
808 String* name) {
809 // ----------- S t a t e -------------
810 // -- eax : value
811 // -- ecx : name
812 // -- esp[0] : return address
813 // -- esp[4] : receiver
814 // -----------------------------------
815
816 HandleScope scope;
817 Label miss;
818
819 // Get the object from the stack.
820 __ mov(ebx, Operand(esp, 1 * kPointerSize));
821
822 // Check that the object isn't a smi.
823 __ test(ebx, Immediate(kSmiTagMask));
824 __ j(zero, &miss, not_taken);
825
826 // Check that the map of the object hasn't changed.
827 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
828 Immediate(Handle<Map>(receiver->map())));
829 __ j(not_equal, &miss, not_taken);
830
831 // Perform global security token check if needed.
832 if (receiver->IsJSGlobalObject()) {
833 __ CheckAccessGlobal(ebx, edx, &miss);
834 }
835
836 // Stub never generated for non-global objects that require access
837 // checks.
838 ASSERT(receiver->IsJSGlobalObject() || !receiver->IsAccessCheckNeeded());
839
840 __ pop(ebx); // remove the return address
841 __ push(Operand(esp, 0)); // receiver
842 __ push(ecx); // name
843 __ push(eax); // value
844 __ push(ebx); // restore return address
845
mads.s.ager31e71382008-08-13 09:32:07 +0000846 // Do tail-call to the runtime system.
847 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000848 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000849 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850
851 // Handle store cache miss.
852 __ bind(&miss);
853 __ mov(Operand(ecx), Immediate(Handle<String>(name))); // restore name
854 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000855 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000856
857 // Return the generated code.
858 return GetCode(INTERCEPTOR);
859}
860
861
862Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
863 int index,
864 Map* transition,
865 String* name) {
866 // ----------- S t a t e -------------
867 // -- eax : value
868 // -- esp[0] : return address
869 // -- esp[4] : key
870 // -- esp[8] : receiver
871 // -----------------------------------
872 HandleScope scope;
873 Label miss;
874
875 __ IncrementCounter(&Counters::keyed_store_field, 1);
876
877 // Get the name from the stack.
878 __ mov(ecx, Operand(esp, 1 * kPointerSize));
879 // Check that the name has not changed.
880 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
881 __ j(not_equal, &miss, not_taken);
882
883 // Get the object from the stack.
884 __ mov(ebx, Operand(esp, 2 * kPointerSize));
885
886 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000887 GenerateStoreField(masm(),
888 Builtins::KeyedStoreIC_ExtendStorage,
889 object,
890 index,
891 transition,
892 ebx, ecx, edx,
893 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000894
895 // Handle store cache miss.
896 __ bind(&miss);
897 __ DecrementCounter(&Counters::keyed_store_field, 1);
898 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000899 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900
901 // Return the generated code.
902 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
903}
904
905
906Object* LoadStubCompiler::CompileLoadField(JSObject* object,
907 JSObject* holder,
908 int index) {
909 // ----------- S t a t e -------------
910 // -- ecx : name
911 // -- esp[0] : return address
912 // -- esp[4] : receiver
913 // -----------------------------------
914
915 HandleScope scope;
916 Label miss;
917
918 __ mov(eax, (Operand(esp, kPointerSize)));
919 GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss);
920 __ bind(&miss);
921 GenerateLoadMiss(masm(), Code::LOAD_IC);
922
923 // Return the generated code.
924 return GetCode(FIELD);
925}
926
927
928Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
929 JSObject* holder,
930 AccessorInfo* callback) {
931 // ----------- S t a t e -------------
932 // -- ecx : name
933 // -- esp[0] : return address
934 // -- esp[4] : receiver
935 // -----------------------------------
936
937 HandleScope scope;
938 Label miss;
939
940 __ mov(eax, (Operand(esp, kPointerSize)));
941 GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx,
942 edx, callback, &miss);
943 __ bind(&miss);
944 GenerateLoadMiss(masm(), Code::LOAD_IC);
945
946 // Return the generated code.
947 return GetCode(CALLBACKS);
948}
949
950
951Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
952 JSObject* holder,
953 Object* value) {
954 // ----------- S t a t e -------------
955 // -- ecx : name
956 // -- esp[0] : return address
957 // -- esp[4] : receiver
958 // -----------------------------------
959
960 HandleScope scope;
961 Label miss;
962
963 __ mov(eax, (Operand(esp, kPointerSize)));
964 GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value, &miss);
965 __ bind(&miss);
966 GenerateLoadMiss(masm(), Code::LOAD_IC);
967
968 // Return the generated code.
969 return GetCode(CONSTANT_FUNCTION);
970}
971
972
973Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
974 JSObject* holder,
975 String* name) {
976 // ----------- S t a t e -------------
977 // -- ecx : name
978 // -- esp[0] : return address
979 // -- esp[4] : receiver
980 // -----------------------------------
981 HandleScope scope;
982 Label miss;
983
984 __ mov(eax, (Operand(esp, kPointerSize)));
985 GenerateLoadInterceptor(masm(), receiver, holder, eax, ecx, edx, ebx, &miss);
986 __ bind(&miss);
987 GenerateLoadMiss(masm(), Code::LOAD_IC);
988
989 // Return the generated code.
990 return GetCode(INTERCEPTOR);
991}
992
993
994Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
995 JSObject* receiver,
996 JSObject* holder,
997 int index) {
998 // ----------- S t a t e -------------
999 // -- esp[0] : return address
1000 // -- esp[4] : name
1001 // -- esp[8] : receiver
1002 // -----------------------------------
1003 HandleScope scope;
1004 Label miss;
1005
1006 __ mov(eax, (Operand(esp, kPointerSize)));
1007 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1008 __ IncrementCounter(&Counters::keyed_load_field, 1);
1009
1010 // Check that the name has not changed.
1011 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1012 __ j(not_equal, &miss, not_taken);
1013
1014 GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss);
1015 __ bind(&miss);
1016 __ DecrementCounter(&Counters::keyed_load_field, 1);
1017 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1018
1019 // Return the generated code.
1020 return GetCode(FIELD);
1021}
1022
1023
1024Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1025 JSObject* receiver,
1026 JSObject* holder,
1027 AccessorInfo* callback) {
1028 // ----------- S t a t e -------------
1029 // -- esp[0] : return address
1030 // -- esp[4] : name
1031 // -- esp[8] : receiver
1032 // -----------------------------------
1033 HandleScope scope;
1034 Label miss;
1035
1036 __ mov(eax, (Operand(esp, kPointerSize)));
1037 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1038 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1039
1040 // Check that the name has not changed.
1041 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1042 __ j(not_equal, &miss, not_taken);
1043
1044 GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx,
1045 callback, &miss);
1046 __ bind(&miss);
1047 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1048 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1049
1050 // Return the generated code.
1051 return GetCode(CALLBACKS);
1052}
1053
1054
1055Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1056 JSObject* receiver,
1057 JSObject* holder,
1058 Object* value) {
1059 // ----------- S t a t e -------------
1060 // -- esp[0] : return address
1061 // -- esp[4] : name
1062 // -- esp[8] : receiver
1063 // -----------------------------------
1064 HandleScope scope;
1065 Label miss;
1066
1067 __ mov(eax, (Operand(esp, kPointerSize)));
1068 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1069 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1070
1071 // Check that the name has not changed.
1072 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1073 __ j(not_equal, &miss, not_taken);
1074
1075 GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value, &miss);
1076 __ bind(&miss);
1077 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1078 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1079
1080 // Return the generated code.
1081 return GetCode(CONSTANT_FUNCTION);
1082}
1083
1084
1085Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1086 JSObject* holder,
1087 String* name) {
1088 // ----------- S t a t e -------------
1089 // -- esp[0] : return address
1090 // -- esp[4] : name
1091 // -- esp[8] : receiver
1092 // -----------------------------------
1093 HandleScope scope;
1094 Label miss;
1095
1096 __ mov(eax, (Operand(esp, kPointerSize)));
1097 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1098 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1099
1100 // Check that the name has not changed.
1101 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1102 __ j(not_equal, &miss, not_taken);
1103
1104 GenerateLoadInterceptor(masm(), receiver, holder, ecx, eax, edx, ebx, &miss);
1105 __ bind(&miss);
1106 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1107 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1108
1109 // Return the generated code.
1110 return GetCode(INTERCEPTOR);
1111}
1112
1113
1114
1115
1116Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1117 // ----------- S t a t e -------------
1118 // -- esp[0] : return address
1119 // -- esp[4] : name
1120 // -- esp[8] : receiver
1121 // -----------------------------------
1122 HandleScope scope;
1123 Label miss;
1124
1125 __ mov(eax, (Operand(esp, kPointerSize)));
1126 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1127 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1128
1129 // Check that the name has not changed.
1130 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1131 __ j(not_equal, &miss, not_taken);
1132
1133 GenerateLoadArrayLength(masm(), ecx, edx, &miss);
1134 __ bind(&miss);
1135 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1136 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1137
1138 // Return the generated code.
1139 return GetCode(CALLBACKS);
1140}
1141
1142
1143Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
1144 // ----------- S t a t e -------------
1145 // -- esp[0] : return address
1146 // -- esp[4] : name
1147 // -- esp[8] : receiver
1148 // -----------------------------------
1149 HandleScope scope;
1150 Label miss;
1151
1152 __ mov(eax, (Operand(esp, kPointerSize)));
1153 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1154 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1155
1156 // Check that the name has not changed.
1157 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1158 __ j(not_equal, &miss, not_taken);
1159
1160 GenerateLoadShortStringLength(masm(), ecx, edx, &miss);
1161 __ bind(&miss);
1162 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1163 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1164
1165 // Return the generated code.
1166 return GetCode(CALLBACKS);
1167}
1168
1169
1170Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name) {
1171 // ----------- S t a t e -------------
1172 // -- esp[0] : return address
1173 // -- esp[4] : name
1174 // -- esp[8] : receiver
1175 // -----------------------------------
1176 HandleScope scope;
1177 Label miss;
1178
1179 __ mov(eax, (Operand(esp, kPointerSize)));
1180 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1181 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1182
1183 // Check that the name has not changed.
1184 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1185 __ j(not_equal, &miss, not_taken);
1186
1187 GenerateLoadMediumStringLength(masm(), ecx, edx, &miss);
1188 __ bind(&miss);
1189 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1190 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1191
1192 // Return the generated code.
1193 return GetCode(CALLBACKS);
1194}
1195
1196
1197Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
1198 // ----------- S t a t e -------------
1199 // -- esp[0] : return address
1200 // -- esp[4] : name
1201 // -- esp[8] : receiver
1202 // -----------------------------------
1203 HandleScope scope;
1204 Label miss;
1205
1206 __ mov(eax, (Operand(esp, kPointerSize)));
1207 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1208 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1209
1210 // Check that the name has not changed.
1211 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1212 __ j(not_equal, &miss, not_taken);
1213
1214 GenerateLoadLongStringLength(masm(), ecx, edx, &miss);
1215 __ bind(&miss);
1216 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1217 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1218
1219 // Return the generated code.
1220 return GetCode(CALLBACKS);
1221}
1222
1223
1224Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1225 // ----------- S t a t e -------------
1226 // -- esp[0] : return address
1227 // -- esp[4] : name
1228 // -- esp[8] : receiver
1229 // -----------------------------------
1230 HandleScope scope;
1231 Label miss;
1232
1233 __ mov(eax, (Operand(esp, kPointerSize)));
1234 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1235 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1236
1237 // Check that the name has not changed.
1238 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1239 __ j(not_equal, &miss, not_taken);
1240
1241 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
1242 __ bind(&miss);
1243 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1244 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1245
1246 // Return the generated code.
1247 return GetCode(CALLBACKS);
1248}
1249
1250
1251#undef __
1252
1253} } // namespace v8::internal