blob: 6c675f99f0329babc1bb7aba4b3a68290a1dec70 [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,
44 Register offset) {
45 ExternalReference key_offset(SCTableReference::keyReference(table));
46 ExternalReference value_offset(SCTableReference::valueReference(table));
47
48 Label miss;
49
50 // Save the offset on the stack.
51 __ push(offset);
52
53 // Check that the key in the entry matches the name.
54 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
55 __ j(not_equal, &miss, not_taken);
56
57 // Get the code entry from the cache.
58 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
59
60 // Check that the flags match what we're looking for.
61 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
kasperl@chromium.org71affb52009-05-26 05:44:31 +000062 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063 __ cmp(offset, flags);
64 __ j(not_equal, &miss);
65
66 // Restore offset and re-load code entry from cache.
67 __ pop(offset);
68 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
69
70 // Jump to the first instruction in the code stub.
71 __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
72 __ jmp(Operand(offset));
73
74 // Miss: Restore offset and fall through.
75 __ bind(&miss);
76 __ pop(offset);
77}
78
79
80void StubCache::GenerateProbe(MacroAssembler* masm,
81 Code::Flags flags,
82 Register receiver,
83 Register name,
84 Register scratch) {
85 Label miss;
86
87 // Make sure that code is valid. The shifting code relies on the
88 // entry size being 8.
89 ASSERT(sizeof(Entry) == 8);
90
91 // Make sure the flags does not name a specific type.
92 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
93
94 // Make sure that there are no register conflicts.
95 ASSERT(!scratch.is(receiver));
96 ASSERT(!scratch.is(name));
97
98 // Check that the receiver isn't a smi.
99 __ test(receiver, Immediate(kSmiTagMask));
100 __ j(zero, &miss, not_taken);
101
102 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000103 __ mov(scratch, FieldOperand(name, String::kLengthOffset));
104 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105 __ xor_(scratch, flags);
106 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
107
108 // Probe the primary table.
109 ProbeTable(masm, flags, kPrimary, name, scratch);
110
111 // Primary miss: Compute hash for secondary probe.
112 __ sub(scratch, Operand(name));
113 __ add(Operand(scratch), Immediate(flags));
114 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
115
116 // Probe the secondary table.
117 ProbeTable(masm, flags, kSecondary, name, scratch);
118
119 // Cache miss: Fall-through and let caller handle the miss by
120 // entering the runtime system.
121 __ bind(&miss);
122}
123
124
125void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
126 int index,
127 Register prototype) {
128 // Load the global or builtins object from the current context.
129 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
130 // Load the global context from the global or builtins object.
131 __ mov(prototype,
132 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
133 // Load the function from the global context.
134 __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
135 // Load the initial map. The global functions all have initial maps.
136 __ mov(prototype,
137 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
138 // Load the prototype from the initial map.
139 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
140}
141
142
143void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
144 Register receiver,
145 Register scratch,
146 Label* miss_label) {
147 // Check that the receiver isn't a smi.
148 __ test(receiver, Immediate(kSmiTagMask));
149 __ j(zero, miss_label, not_taken);
150
151 // Check that the object is a JS array.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000152 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153 __ j(not_equal, miss_label, not_taken);
154
155 // Load length directly from the JS array.
156 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
157 __ ret(0);
158}
159
160
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000161// Generate code to check if an object is a string. If the object is
162// a string, the map's instance type is left in the scratch register.
163static void GenerateStringCheck(MacroAssembler* masm,
164 Register receiver,
165 Register scratch,
166 Label* smi,
167 Label* non_string_object) {
168 // Check that the object isn't a smi.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 __ test(receiver, Immediate(kSmiTagMask));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000170 __ j(zero, smi, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000171
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000172 // Check that the object is a string.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
174 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000175 ASSERT(kNotStringTag != 0);
176 __ test(scratch, Immediate(kNotStringTag));
177 __ j(not_zero, non_string_object, not_taken);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178}
179
180
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000181void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
182 Register receiver,
183 Register scratch,
184 Label* miss) {
185 Label load_length, check_wrapper;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000186
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000187 // Check if the object is a string leaving the instance type in the
188 // scratch register.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000189 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190
191 // Load length directly from the string.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000192 __ bind(&load_length);
193 __ and_(scratch, kStringSizeMask);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000195 // ecx is also the receiver.
196 __ lea(ecx, Operand(scratch, String::kLongLengthShift));
197 __ shr(eax); // ecx is implicit shift register.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198 __ shl(eax, kSmiTagSize);
199 __ ret(0);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000200
201 // Check if the object is a JSValue wrapper.
202 __ bind(&check_wrapper);
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000203 __ cmp(scratch, JS_VALUE_TYPE);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000204 __ j(not_equal, miss, not_taken);
205
206 // Check if the wrapped value is a string and load the length
207 // directly if it is.
208 __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
209 GenerateStringCheck(masm, receiver, scratch, miss, miss);
210 __ jmp(&load_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211}
212
213
214void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
215 Register receiver,
216 Register scratch1,
217 Register scratch2,
218 Label* miss_label) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000219 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220 __ mov(eax, Operand(scratch1));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 __ ret(0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000222}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223
ager@chromium.org7c537e22008-10-16 08:43:32 +0000224
225// Load a fast property out of a holder object (src). In-object properties
226// are loaded directly otherwise the property is loaded from the properties
227// fixed array.
228void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000229 Register dst, Register src,
230 JSObject* holder, int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000231 // Adjust for the number of properties stored in the holder.
232 index -= holder->map()->inobject_properties();
233 if (index < 0) {
234 // Get the property straight out of the holder.
235 int offset = holder->map()->instance_size() + (index * kPointerSize);
236 __ mov(dst, FieldOperand(src, offset));
237 } else {
238 // Calculate the offset into the properties array.
239 int offset = index * kPointerSize + Array::kHeaderSize;
240 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
241 __ mov(dst, FieldOperand(dst, offset));
242 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243}
244
245
246void StubCompiler::GenerateLoadField(MacroAssembler* masm,
247 JSObject* object,
248 JSObject* holder,
249 Register receiver,
250 Register scratch1,
251 Register scratch2,
252 int index,
253 Label* miss_label) {
254 // Check that the receiver isn't a smi.
255 __ test(receiver, Immediate(kSmiTagMask));
256 __ j(zero, miss_label, not_taken);
257
258 // Check that the maps haven't changed.
259 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000260 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000261
ager@chromium.org7c537e22008-10-16 08:43:32 +0000262 // Get the value from the properties.
263 GenerateFastPropertyLoad(masm, eax, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000264 __ ret(0);
265}
266
267
268void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
269 JSObject* object,
270 JSObject* holder,
271 Register receiver,
272 Register name,
273 Register scratch1,
274 Register scratch2,
275 AccessorInfo* callback,
276 Label* miss_label) {
277 // Check that the receiver isn't a smi.
278 __ test(receiver, Immediate(kSmiTagMask));
279 __ j(zero, miss_label, not_taken);
280
281 // Check that the maps haven't changed.
282 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000283 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284
285 // Push the arguments on the JS stack of the caller.
286 __ pop(scratch2); // remove return address
287 __ push(receiver); // receiver
288 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data
289 __ push(name); // name
290 __ push(reg); // holder
291 __ push(scratch2); // restore return address
292
mads.s.ager31e71382008-08-13 09:32:07 +0000293 // Do tail-call to the runtime system.
294 ExternalReference load_callback_property =
295 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
296 __ TailCallRuntime(load_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297}
298
299
300void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
301 JSObject* object,
302 JSObject* holder,
303 Register receiver,
304 Register scratch1,
305 Register scratch2,
306 Object* value,
307 Label* miss_label) {
308 // Check that the receiver isn't a smi.
309 __ test(receiver, Immediate(kSmiTagMask));
310 __ j(zero, miss_label, not_taken);
311
312 // Check that the maps haven't changed.
313 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000314 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315
316 // Return the constant value.
317 __ mov(eax, Handle<Object>(value));
318 __ ret(0);
319}
320
321
322void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
323 JSObject* object,
324 JSObject* holder,
325 Register receiver,
326 Register name,
327 Register scratch1,
328 Register scratch2,
329 Label* miss_label) {
330 // Check that the receiver isn't a smi.
331 __ test(receiver, Immediate(kSmiTagMask));
332 __ j(zero, miss_label, not_taken);
333
334 // Check that the maps haven't changed.
335 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000336 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337
338 // Push the arguments on the JS stack of the caller.
339 __ pop(scratch2); // remove return address
340 __ push(receiver); // receiver
341 __ push(reg); // holder
342 __ push(name); // name
343 __ push(scratch2); // restore return address
344
mads.s.ager31e71382008-08-13 09:32:07 +0000345 // Do tail-call to the runtime system.
346 ExternalReference load_ic_property =
347 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
348 __ TailCallRuntime(load_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349}
350
351
352void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
353 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
354 Code* code = NULL;
355 if (kind == Code::LOAD_IC) {
356 code = Builtins::builtin(Builtins::LoadIC_Miss);
357 } else {
358 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
359 }
360
361 Handle<Code> ic(code);
ager@chromium.org236ad962008-09-25 09:45:57 +0000362 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000363}
364
365
366void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000367 Builtins::Name storage_extend,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 JSObject* object,
369 int index,
370 Map* transition,
371 Register receiver_reg,
372 Register name_reg,
373 Register scratch,
374 Label* miss_label) {
375 // Check that the object isn't a smi.
376 __ test(receiver_reg, Immediate(kSmiTagMask));
377 __ j(zero, miss_label, not_taken);
378
379 // Check that the map of the object hasn't changed.
380 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
381 Immediate(Handle<Map>(object->map())));
382 __ j(not_equal, miss_label, not_taken);
383
384 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000385 if (object->IsJSGlobalProxy()) {
386 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 }
388
389 // Stub never generated for non-global objects that require access
390 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000391 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000393 // Perform map transition for the receiver if necessary.
394 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
395 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000396 // We jump to a runtime call that extends the properties array.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000397 __ mov(ecx, Immediate(Handle<Map>(transition)));
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000398 Handle<Code> ic(Builtins::builtin(storage_extend));
399 __ jmp(ic, RelocInfo::CODE_TARGET);
400 return;
401 }
402
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403 if (transition != NULL) {
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000404 // Update the map of the object; no write barrier updating is
405 // needed because the map is never in new space.
406 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
407 Immediate(Handle<Map>(transition)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408 }
409
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000410 // Adjust for the number of properties stored in the object. Even in the
411 // face of a transition we can use the old map here because the size of the
412 // object and the number of in-object properties is not going to change.
413 index -= object->map()->inobject_properties();
414
ager@chromium.org7c537e22008-10-16 08:43:32 +0000415 if (index < 0) {
416 // Set the property straight into the object.
417 int offset = object->map()->instance_size() + (index * kPointerSize);
418 __ mov(FieldOperand(receiver_reg, offset), eax);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000419
ager@chromium.org7c537e22008-10-16 08:43:32 +0000420 // Update the write barrier for the array address.
421 // Pass the value being stored in the now unused name_reg.
422 __ mov(name_reg, Operand(eax));
423 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
424 } else {
425 // Write to the properties array.
426 int offset = index * kPointerSize + Array::kHeaderSize;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000427 // Get the properties array (optimistically).
428 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
ager@chromium.org7c537e22008-10-16 08:43:32 +0000429 __ mov(FieldOperand(scratch, offset), eax);
430
431 // Update the write barrier for the array address.
432 // Pass the value being stored in the now unused name_reg.
433 __ mov(name_reg, Operand(eax));
434 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
435 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000436
437 // Return the value (register eax).
438 __ ret(0);
439}
440
441
442#undef __
443
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000444#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445
446
447// TODO(1241006): Avoid having lazy compile stubs specialized by the
448// number of arguments. It is not needed anymore.
449Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000450 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000451 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000452
453 // Push a copy of the function onto the stack.
454 __ push(edi);
455
456 __ push(edi); // function is also the parameter to the runtime call
457 __ CallRuntime(Runtime::kLazyCompile, 1);
458 __ pop(edi);
459
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000460 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000461 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462
463 // Do a tail-call of the compiled function.
464 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
465 __ jmp(Operand(ecx));
466
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000467 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468}
469
470
471Object* CallStubCompiler::CompileCallField(Object* object,
472 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000473 int index,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000474 String* name,
475 Code::Flags flags) {
476 ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477 // ----------- S t a t e -------------
478 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479 Label miss;
480
481 // Get the receiver from the stack.
482 const int argc = arguments().immediate();
483 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
484
485 // Check that the receiver isn't a smi.
486 __ test(edx, Immediate(kSmiTagMask));
487 __ j(zero, &miss, not_taken);
488
489 // Do the right check and compute the holder register.
490 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000491 masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492
ager@chromium.org7c537e22008-10-16 08:43:32 +0000493 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000494
495 // Check that the function really is a function.
496 __ test(edi, Immediate(kSmiTagMask));
497 __ j(zero, &miss, not_taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000498 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 __ j(not_equal, &miss, not_taken);
500
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000501 // Patch the receiver on the stack with the global proxy if
502 // necessary.
503 if (object->IsGlobalObject()) {
504 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
505 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
506 }
507
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 // Invoke the function.
509 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
510
511 // Handle call cache miss.
512 __ bind(&miss);
513 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000514 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515
516 // Return the generated code.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000517 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518}
519
520
521Object* CallStubCompiler::CompileCallConstant(Object* object,
522 JSObject* holder,
523 JSFunction* function,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000524 CheckType check,
525 Code::Flags flags) {
526 ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527 // ----------- S t a t e -------------
528 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529 Label miss;
530
531 // Get the receiver from the stack.
532 const int argc = arguments().immediate();
533 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
534
535 // Check that the receiver isn't a smi.
536 if (check != NUMBER_CHECK) {
537 __ test(edx, Immediate(kSmiTagMask));
538 __ j(zero, &miss, not_taken);
539 }
540
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000541 // Make sure that it's okay not to patch the on stack receiver
542 // unless we're doing a receiver map check.
543 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
544
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545 switch (check) {
546 case RECEIVER_MAP_CHECK:
547 // Check that the maps haven't changed.
548 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000549
550 // Patch the receiver on the stack with the global proxy if
551 // necessary.
552 if (object->IsGlobalObject()) {
553 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
554 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
555 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556 break;
557
558 case STRING_CHECK:
559 // Check that the object is a two-byte string or a symbol.
560 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
561 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
562 __ cmp(ecx, FIRST_NONSTRING_TYPE);
563 __ j(above_equal, &miss, not_taken);
564 // Check that the maps starting from the prototype haven't changed.
565 GenerateLoadGlobalFunctionPrototype(masm(),
566 Context::STRING_FUNCTION_INDEX,
567 ecx);
568 __ CheckMaps(JSObject::cast(object->GetPrototype()),
569 ecx, holder, ebx, edx, &miss);
570 break;
571
572 case NUMBER_CHECK: {
573 Label fast;
574 // Check that the object is a smi or a heap number.
575 __ test(edx, Immediate(kSmiTagMask));
576 __ j(zero, &fast, taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000577 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578 __ j(not_equal, &miss, not_taken);
579 __ bind(&fast);
580 // Check that the maps starting from the prototype haven't changed.
581 GenerateLoadGlobalFunctionPrototype(masm(),
582 Context::NUMBER_FUNCTION_INDEX,
583 ecx);
584 __ CheckMaps(JSObject::cast(object->GetPrototype()),
585 ecx, holder, ebx, edx, &miss);
586 break;
587 }
588
589 case BOOLEAN_CHECK: {
590 Label fast;
591 // Check that the object is a boolean.
592 __ cmp(edx, Factory::true_value());
593 __ j(equal, &fast, taken);
594 __ cmp(edx, Factory::false_value());
595 __ j(not_equal, &miss, not_taken);
596 __ bind(&fast);
597 // Check that the maps starting from the prototype haven't changed.
598 GenerateLoadGlobalFunctionPrototype(masm(),
599 Context::BOOLEAN_FUNCTION_INDEX,
600 ecx);
601 __ CheckMaps(JSObject::cast(object->GetPrototype()),
602 ecx, holder, ebx, edx, &miss);
603 break;
604 }
605
606 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
607 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
608 // Make sure object->elements()->map() != Heap::dictionary_array_map()
609 // Get the elements array of the object.
610 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
611 // Check that the object is in fast mode (not dictionary).
612 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
613 Immediate(Factory::hash_table_map()));
614 __ j(equal, &miss, not_taken);
615 break;
616
617 default:
618 UNREACHABLE();
619 }
620
621 // Get the function and setup the context.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000622 __ mov(edi, Immediate(Handle<JSFunction>(function)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000623 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
624
625 // Jump to the cached code (tail call).
626 Handle<Code> code(function->code());
627 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000628 __ InvokeCode(code, expected, arguments(),
629 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630
631 // Handle call cache miss.
632 __ bind(&miss);
633 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000634 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000635
636 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000637 String* function_name = NULL;
638 if (function->shared()->name()->IsString()) {
639 function_name = String::cast(function->shared()->name());
640 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000641 return GetCodeWithFlags(flags, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642}
643
644
645Object* CallStubCompiler::CompileCallInterceptor(Object* object,
646 JSObject* holder,
647 String* name) {
648 // ----------- S t a t e -------------
649 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650 Label miss;
651
652 // Get the number of arguments.
653 const int argc = arguments().immediate();
654
655 // Get the receiver from the stack.
656 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000657
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658 // Check that the receiver isn't a smi.
659 __ test(edx, Immediate(kSmiTagMask));
660 __ j(zero, &miss, not_taken);
661
662 // Check that maps have not changed and compute the holder register.
663 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000664 masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665
666 // Enter an internal frame.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000667 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668
669 // Push arguments on the expression stack.
670 __ push(edx); // receiver
671 __ push(reg); // holder
672 __ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
673
674 // Perform call.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675 ExternalReference load_interceptor =
676 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000677 __ mov(eax, Immediate(3));
678 __ mov(ebx, Immediate(load_interceptor));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679
680 CEntryStub stub;
681 __ CallStub(&stub);
682
683 // Move result to edi and restore receiver.
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000684 __ mov(edi, eax);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685 __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize)); // receiver
686
687 // Exit frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000688 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689
690 // Check that the function really is a function.
691 __ test(edi, Immediate(kSmiTagMask));
692 __ j(zero, &miss, not_taken);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000693 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000694 __ j(not_equal, &miss, not_taken);
695
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000696 // Patch the receiver on the stack with the global proxy if
697 // necessary.
698 if (object->IsGlobalObject()) {
699 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
700 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
701 }
702
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000703 // Invoke the function.
704 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
705
706 // Handle load cache miss.
707 __ bind(&miss);
708 Handle<Code> ic = ComputeCallMiss(argc);
ager@chromium.org236ad962008-09-25 09:45:57 +0000709 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710
711 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000712 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713}
714
715
716Object* StoreStubCompiler::CompileStoreField(JSObject* object,
717 int index,
718 Map* transition,
719 String* name) {
720 // ----------- S t a t e -------------
721 // -- eax : value
722 // -- ecx : name
723 // -- esp[0] : return address
724 // -- esp[4] : receiver
725 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000726 Label miss;
727
728 // Get the object from the stack.
729 __ mov(ebx, Operand(esp, 1 * kPointerSize));
730
731 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000732 GenerateStoreField(masm(),
733 Builtins::StoreIC_ExtendStorage,
734 object,
735 index,
736 transition,
737 ebx, ecx, edx,
738 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739
740 // Handle store cache miss.
741 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000742 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000744 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745
746 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000747 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000748}
749
750
751Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
752 AccessorInfo* callback,
753 String* name) {
754 // ----------- S t a t e -------------
755 // -- eax : value
756 // -- ecx : name
757 // -- esp[0] : return address
758 // -- esp[4] : receiver
759 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 Label miss;
761
762 // Get the object from the stack.
763 __ mov(ebx, Operand(esp, 1 * kPointerSize));
764
765 // Check that the object isn't a smi.
766 __ test(ebx, Immediate(kSmiTagMask));
767 __ j(zero, &miss, not_taken);
768
769 // Check that the map of the object hasn't changed.
770 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
771 Immediate(Handle<Map>(object->map())));
772 __ j(not_equal, &miss, not_taken);
773
774 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000775 if (object->IsJSGlobalProxy()) {
776 __ CheckAccessGlobalProxy(ebx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000777 }
778
779 // Stub never generated for non-global objects that require access
780 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000781 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000782
783 __ pop(ebx); // remove the return address
784 __ push(Operand(esp, 0)); // receiver
785 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info
786 __ push(ecx); // name
787 __ push(eax); // value
788 __ push(ebx); // restore return address
789
mads.s.ager31e71382008-08-13 09:32:07 +0000790 // Do tail-call to the runtime system.
791 ExternalReference store_callback_property =
792 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
793 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794
795 // Handle store cache miss.
796 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000797 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000798 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000799 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800
801 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000802 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000803}
804
805
806Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
807 String* name) {
808 // ----------- S t a t e -------------
809 // -- eax : value
810 // -- ecx : name
811 // -- esp[0] : return address
812 // -- esp[4] : receiver
813 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000814 Label miss;
815
816 // Get the object from the stack.
817 __ mov(ebx, Operand(esp, 1 * kPointerSize));
818
819 // Check that the object isn't a smi.
820 __ test(ebx, Immediate(kSmiTagMask));
821 __ j(zero, &miss, not_taken);
822
823 // Check that the map of the object hasn't changed.
824 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
825 Immediate(Handle<Map>(receiver->map())));
826 __ j(not_equal, &miss, not_taken);
827
828 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000829 if (receiver->IsJSGlobalProxy()) {
830 __ CheckAccessGlobalProxy(ebx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000831 }
832
833 // Stub never generated for non-global objects that require access
834 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000835 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836
837 __ pop(ebx); // remove the return address
838 __ push(Operand(esp, 0)); // receiver
839 __ push(ecx); // name
840 __ push(eax); // value
841 __ push(ebx); // restore return address
842
mads.s.ager31e71382008-08-13 09:32:07 +0000843 // Do tail-call to the runtime system.
844 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000846 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000847
848 // Handle store cache miss.
849 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000850 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000852 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853
854 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000855 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000856}
857
858
859Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
860 int index,
861 Map* transition,
862 String* name) {
863 // ----------- S t a t e -------------
864 // -- eax : value
865 // -- esp[0] : return address
866 // -- esp[4] : key
867 // -- esp[8] : receiver
868 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869 Label miss;
870
871 __ IncrementCounter(&Counters::keyed_store_field, 1);
872
873 // Get the name from the stack.
874 __ mov(ecx, Operand(esp, 1 * kPointerSize));
875 // Check that the name has not changed.
876 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
877 __ j(not_equal, &miss, not_taken);
878
879 // Get the object from the stack.
880 __ mov(ebx, Operand(esp, 2 * kPointerSize));
881
882 // Generate store field code. Trashes the name register.
kasperl@chromium.org1accd572008-10-07 10:57:21 +0000883 GenerateStoreField(masm(),
884 Builtins::KeyedStoreIC_ExtendStorage,
885 object,
886 index,
887 transition,
888 ebx, ecx, edx,
889 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890
891 // Handle store cache miss.
892 __ bind(&miss);
893 __ DecrementCounter(&Counters::keyed_store_field, 1);
894 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000895 __ jmp(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896
897 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000898 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899}
900
901
902Object* LoadStubCompiler::CompileLoadField(JSObject* object,
903 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000904 int index,
905 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000906 // ----------- S t a t e -------------
907 // -- ecx : name
908 // -- esp[0] : return address
909 // -- esp[4] : receiver
910 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911 Label miss;
912
913 __ mov(eax, (Operand(esp, kPointerSize)));
914 GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss);
915 __ bind(&miss);
916 GenerateLoadMiss(masm(), Code::LOAD_IC);
917
918 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000919 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000920}
921
922
923Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
924 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000925 AccessorInfo* callback,
926 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000927 // ----------- S t a t e -------------
928 // -- ecx : name
929 // -- esp[0] : return address
930 // -- esp[4] : receiver
931 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000932 Label miss;
933
934 __ mov(eax, (Operand(esp, kPointerSize)));
935 GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx,
936 edx, callback, &miss);
937 __ bind(&miss);
938 GenerateLoadMiss(masm(), Code::LOAD_IC);
939
940 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000941 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942}
943
944
945Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
946 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000947 Object* value,
948 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000949 // ----------- S t a t e -------------
950 // -- ecx : name
951 // -- esp[0] : return address
952 // -- esp[4] : receiver
953 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954 Label miss;
955
956 __ mov(eax, (Operand(esp, kPointerSize)));
957 GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value, &miss);
958 __ bind(&miss);
959 GenerateLoadMiss(masm(), Code::LOAD_IC);
960
961 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000962 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963}
964
965
966Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
967 JSObject* holder,
968 String* name) {
969 // ----------- S t a t e -------------
970 // -- ecx : name
971 // -- esp[0] : return address
972 // -- esp[4] : receiver
973 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000974 Label miss;
975
976 __ mov(eax, (Operand(esp, kPointerSize)));
977 GenerateLoadInterceptor(masm(), receiver, holder, eax, ecx, edx, ebx, &miss);
978 __ bind(&miss);
979 GenerateLoadMiss(masm(), Code::LOAD_IC);
980
981 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000982 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000983}
984
985
986Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
987 JSObject* receiver,
988 JSObject* holder,
989 int index) {
990 // ----------- S t a t e -------------
991 // -- esp[0] : return address
992 // -- esp[4] : name
993 // -- esp[8] : receiver
994 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995 Label miss;
996
997 __ mov(eax, (Operand(esp, kPointerSize)));
998 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
999 __ IncrementCounter(&Counters::keyed_load_field, 1);
1000
1001 // Check that the name has not changed.
1002 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1003 __ j(not_equal, &miss, not_taken);
1004
1005 GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss);
1006 __ bind(&miss);
1007 __ DecrementCounter(&Counters::keyed_load_field, 1);
1008 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1009
1010 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001011 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001012}
1013
1014
1015Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1016 JSObject* receiver,
1017 JSObject* holder,
1018 AccessorInfo* callback) {
1019 // ----------- S t a t e -------------
1020 // -- esp[0] : return address
1021 // -- esp[4] : name
1022 // -- esp[8] : receiver
1023 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001024 Label miss;
1025
1026 __ mov(eax, (Operand(esp, kPointerSize)));
1027 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1028 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1029
1030 // Check that the name has not changed.
1031 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1032 __ j(not_equal, &miss, not_taken);
1033
1034 GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx,
1035 callback, &miss);
1036 __ bind(&miss);
1037 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1038 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1039
1040 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001041 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001042}
1043
1044
1045Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1046 JSObject* receiver,
1047 JSObject* holder,
1048 Object* value) {
1049 // ----------- S t a t e -------------
1050 // -- esp[0] : return address
1051 // -- esp[4] : name
1052 // -- esp[8] : receiver
1053 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001054 Label miss;
1055
1056 __ mov(eax, (Operand(esp, kPointerSize)));
1057 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1058 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1059
1060 // Check that the name has not changed.
1061 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1062 __ j(not_equal, &miss, not_taken);
1063
1064 GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value, &miss);
1065 __ bind(&miss);
1066 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1067 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1068
1069 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001070 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071}
1072
1073
1074Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1075 JSObject* holder,
1076 String* name) {
1077 // ----------- S t a t e -------------
1078 // -- esp[0] : return address
1079 // -- esp[4] : name
1080 // -- esp[8] : receiver
1081 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001082 Label miss;
1083
1084 __ mov(eax, (Operand(esp, kPointerSize)));
1085 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1086 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1087
1088 // Check that the name has not changed.
1089 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1090 __ j(not_equal, &miss, not_taken);
1091
1092 GenerateLoadInterceptor(masm(), receiver, holder, ecx, eax, edx, ebx, &miss);
1093 __ bind(&miss);
1094 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1095 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1096
1097 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001098 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099}
1100
1101
1102
1103
1104Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1105 // ----------- S t a t e -------------
1106 // -- esp[0] : return address
1107 // -- esp[4] : name
1108 // -- esp[8] : receiver
1109 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001110 Label miss;
1111
1112 __ mov(eax, (Operand(esp, kPointerSize)));
1113 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1114 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1115
1116 // Check that the name has not changed.
1117 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1118 __ j(not_equal, &miss, not_taken);
1119
1120 GenerateLoadArrayLength(masm(), ecx, edx, &miss);
1121 __ bind(&miss);
1122 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1123 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1124
1125 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001126 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001127}
1128
1129
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001130Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001131 // ----------- S t a t e -------------
1132 // -- esp[0] : return address
1133 // -- esp[4] : name
1134 // -- esp[8] : receiver
1135 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001136 Label miss;
1137
1138 __ mov(eax, (Operand(esp, kPointerSize)));
1139 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1140 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1141
1142 // Check that the name has not changed.
1143 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1144 __ j(not_equal, &miss, not_taken);
1145
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001146 GenerateLoadStringLength(masm(), ecx, edx, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147 __ bind(&miss);
1148 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1149 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1150
1151 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001152 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153}
1154
1155
1156Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1157 // ----------- S t a t e -------------
1158 // -- esp[0] : return address
1159 // -- esp[4] : name
1160 // -- esp[8] : receiver
1161 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162 Label miss;
1163
1164 __ mov(eax, (Operand(esp, kPointerSize)));
1165 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1166 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1167
1168 // Check that the name has not changed.
1169 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1170 __ j(not_equal, &miss, not_taken);
1171
1172 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
1173 __ bind(&miss);
1174 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1175 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1176
1177 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001178 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001179}
1180
1181
1182#undef __
1183
1184} } // namespace v8::internal