Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 92068: Move backend specific files to separate directories. (Closed)
Patch Set: Added CPPPATH flag and made all includes use same base path. Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ia32/frames-ia32.cc ('k') | src/ia32/jump-target-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // 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 "codegen-inl.h"
31 #include "ic-inl.h"
32 #include "runtime.h"
33 #include "stub-cache.h"
34
35 namespace v8 { namespace internal {
36
37 // ----------------------------------------------------------------------------
38 // Static IC stub generators.
39 //
40
41 #define __ ACCESS_MASM(masm)
42
43
44 // Helper function used to load a property from a dictionary backing storage.
45 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
46 Register r0, Register r1, Register r2,
47 Register name) {
48 // Register use:
49 //
50 // r0 - used to hold the property dictionary.
51 //
52 // r1 - initially the receiver
53 // - used for the index into the property dictionary
54 // - holds the result on exit.
55 //
56 // r2 - used to hold the capacity of the property dictionary.
57 //
58 // name - holds the name of the property and is unchanges.
59
60 Label done;
61
62 // Check for the absence of an interceptor.
63 // Load the map into r0.
64 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset));
65 // Test the has_named_interceptor bit in the map.
66 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
67 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
68 // Jump to miss if the interceptor bit is set.
69 __ j(not_zero, miss_label, not_taken);
70
71 // Check that the properties array is a dictionary.
72 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
73 __ cmp(FieldOperand(r0, HeapObject::kMapOffset),
74 Immediate(Factory::hash_table_map()));
75 __ j(not_equal, miss_label);
76
77 // Compute the capacity mask.
78 const int kCapacityOffset =
79 Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
80 __ mov(r2, FieldOperand(r0, kCapacityOffset));
81 __ shr(r2, kSmiTagSize); // convert smi to int
82 __ dec(r2);
83
84 // Generate an unrolled loop that performs a few probes before
85 // giving up. Measurements done on Gmail indicate that 2 probes
86 // cover ~93% of loads from dictionaries.
87 static const int kProbes = 4;
88 const int kElementsStartOffset =
89 Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
90 for (int i = 0; i < kProbes; i++) {
91 // Compute the masked index: (hash + i + i * i) & mask.
92 __ mov(r1, FieldOperand(name, String::kLengthOffset));
93 __ shr(r1, String::kHashShift);
94 if (i > 0) {
95 __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
96 }
97 __ and_(r1, Operand(r2));
98
99 // Scale the index by multiplying by the element size.
100 ASSERT(Dictionary::kElementSize == 3);
101 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
102
103 // Check if the key is identical to the name.
104 __ cmp(name,
105 Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag));
106 if (i != kProbes - 1) {
107 __ j(equal, &done, taken);
108 } else {
109 __ j(not_equal, miss_label, not_taken);
110 }
111 }
112
113 // Check that the value is a normal property.
114 __ bind(&done);
115 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
116 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
117 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
118 __ j(not_zero, miss_label, not_taken);
119
120 // Get the value at the masked, scaled index.
121 const int kValueOffset = kElementsStartOffset + kPointerSize;
122 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
123 }
124
125
126 // Helper function used to check that a value is either not a function
127 // or is loaded if it is a function.
128 static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm, Label* miss,
129 Register value, Register scratch) {
130 Label done;
131 // Check if the value is a Smi.
132 __ test(value, Immediate(kSmiTagMask));
133 __ j(zero, &done, not_taken);
134 // Check if the value is a function.
135 __ CmpObjectType(value, JS_FUNCTION_TYPE, scratch);
136 __ j(not_equal, &done, taken);
137 // Check if the function has been loaded.
138 __ mov(scratch, FieldOperand(value, JSFunction::kSharedFunctionInfoOffset));
139 __ mov(scratch,
140 FieldOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
141 __ cmp(scratch, Factory::undefined_value());
142 __ j(not_equal, miss, not_taken);
143 __ bind(&done);
144 }
145
146
147 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
148 // ----------- S t a t e -------------
149 // -- ecx : name
150 // -- esp[0] : return address
151 // -- esp[4] : receiver
152 // -----------------------------------
153
154 Label miss;
155
156 __ mov(eax, Operand(esp, kPointerSize));
157
158 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
159 __ bind(&miss);
160 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
161 }
162
163
164 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
165 // ----------- S t a t e -------------
166 // -- ecx : name
167 // -- esp[0] : return address
168 // -- esp[4] : receiver
169 // -----------------------------------
170
171 Label miss;
172
173 __ mov(eax, Operand(esp, kPointerSize));
174
175 StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
176 __ bind(&miss);
177 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
178 }
179
180
181 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
182 // ----------- S t a t e -------------
183 // -- ecx : name
184 // -- esp[0] : return address
185 // -- esp[4] : receiver
186 // -----------------------------------
187
188 Label miss;
189
190 __ mov(eax, Operand(esp, kPointerSize));
191
192 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
193 __ bind(&miss);
194 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
195 }
196
197
198 #ifdef DEBUG
199 // For use in assert below.
200 static int TenToThe(int exponent) {
201 ASSERT(exponent <= 9);
202 ASSERT(exponent >= 1);
203 int answer = 10;
204 for (int i = 1; i < exponent; i++) answer *= 10;
205 return answer;
206 }
207 #endif
208
209
210 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
211 // ----------- S t a t e -------------
212 // -- esp[0] : return address
213 // -- esp[4] : name
214 // -- esp[8] : receiver
215 // -----------------------------------
216 Label slow, fast, check_string, index_int, index_string;
217
218 // Load name and receiver.
219 __ mov(eax, (Operand(esp, kPointerSize)));
220 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
221
222 // Check that the object isn't a smi.
223 __ test(ecx, Immediate(kSmiTagMask));
224 __ j(zero, &slow, not_taken);
225
226 // Get the map of the receiver.
227 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
228 // Check that the receiver does not require access checks. We need
229 // to check this explicitly since this generic stub does not perform
230 // map checks.
231 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
232 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
233 __ j(not_zero, &slow, not_taken);
234 // Check that the object is some kind of JS object EXCEPT JS Value type.
235 // In the case that the object is a value-wrapper object,
236 // we enter the runtime system to make sure that indexing
237 // into string objects work as intended.
238 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
239 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
240 __ cmp(edx, JS_OBJECT_TYPE);
241 __ j(less, &slow, not_taken);
242 // Check that the key is a smi.
243 __ test(eax, Immediate(kSmiTagMask));
244 __ j(not_zero, &check_string, not_taken);
245 __ sar(eax, kSmiTagSize);
246 // Get the elements array of the object.
247 __ bind(&index_int);
248 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
249 // Check that the object is in fast mode (not dictionary).
250 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
251 Immediate(Factory::hash_table_map()));
252 __ j(equal, &slow, not_taken);
253 // Check that the key (index) is within bounds.
254 __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset));
255 __ j(below, &fast, taken);
256 // Slow case: Load name and receiver from stack and jump to runtime.
257 __ bind(&slow);
258 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
259 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
260 // Check if the key is a symbol that is not an array index.
261 __ bind(&check_string);
262 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
263 __ test(ebx, Immediate(String::kIsArrayIndexMask));
264 __ j(not_zero, &index_string, not_taken);
265 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
266 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
267 __ test(ebx, Immediate(kIsSymbolMask));
268 __ j(not_zero, &slow, not_taken);
269 // Probe the dictionary leaving result in ecx.
270 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
271 GenerateCheckNonFunctionOrLoaded(masm, &slow, ecx, edx);
272 __ mov(eax, Operand(ecx));
273 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
274 __ ret(0);
275 // Array index string: If short enough use cache in length/hash field (ebx).
276 // We assert that there are enough bits in an int32_t after the hash shift
277 // bits have been subtracted to allow space for the length and the cached
278 // array index.
279 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
280 (1 << (String::kShortLengthShift - String::kHashShift)));
281 __ bind(&index_string);
282 const int kLengthFieldLimit =
283 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
284 __ cmp(ebx, kLengthFieldLimit);
285 __ j(above_equal, &slow);
286 __ mov(eax, Operand(ebx));
287 __ and_(eax, (1 << String::kShortLengthShift) - 1);
288 __ shr(eax, String::kLongLengthShift);
289 __ jmp(&index_int);
290 // Fast case: Do the load.
291 __ bind(&fast);
292 __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
293 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
294 // In case the loaded value is the_hole we have to consult GetProperty
295 // to ensure the prototype chain is searched.
296 __ j(equal, &slow, not_taken);
297 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
298 __ ret(0);
299 }
300
301
302 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
303 // ----------- S t a t e -------------
304 // -- eax : value
305 // -- esp[0] : return address
306 // -- esp[4] : key
307 // -- esp[8] : receiver
308 // -----------------------------------
309 Label slow, fast, array, extra;
310
311 // Get the receiver from the stack.
312 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key
313 // Check that the object isn't a smi.
314 __ test(edx, Immediate(kSmiTagMask));
315 __ j(zero, &slow, not_taken);
316 // Get the map from the receiver.
317 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
318 // Check that the receiver does not require access checks. We need
319 // to do this because this generic stub does not perform map checks.
320 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
321 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
322 __ j(not_zero, &slow, not_taken);
323 // Get the key from the stack.
324 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
325 // Check that the key is a smi.
326 __ test(ebx, Immediate(kSmiTagMask));
327 __ j(not_zero, &slow, not_taken);
328 // Get the instance type from the map of the receiver.
329 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
330 // Check if the object is a JS array or not.
331 __ cmp(ecx, JS_ARRAY_TYPE);
332 __ j(equal, &array);
333 // Check that the object is some kind of JS object.
334 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
335 __ j(less, &slow, not_taken);
336
337 // Object case: Check key against length in the elements array.
338 // eax: value
339 // edx: JSObject
340 // ebx: index (as a smi)
341 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
342 // Check that the object is in fast mode (not dictionary).
343 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
344 Immediate(Factory::hash_table_map()));
345 __ j(equal, &slow, not_taken);
346 // Untag the key (for checking against untagged length in the fixed array).
347 __ mov(edx, Operand(ebx));
348 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison
349 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset));
350 // eax: value
351 // ecx: FixedArray
352 // ebx: index (as a smi)
353 __ j(below, &fast, taken);
354
355
356 // Slow case: Push extra copies of the arguments (3).
357 __ bind(&slow);
358 __ pop(ecx);
359 __ push(Operand(esp, 1 * kPointerSize));
360 __ push(Operand(esp, 1 * kPointerSize));
361 __ push(eax);
362 __ push(ecx);
363 // Do tail-call to runtime routine.
364 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
365
366
367 // Extra capacity case: Check if there is extra capacity to
368 // perform the store and update the length. Used for adding one
369 // element to the array by writing to array[array.length].
370 __ bind(&extra);
371 // eax: value
372 // edx: JSArray
373 // ecx: FixedArray
374 // ebx: index (as a smi)
375 // flags: compare (ebx, edx.length())
376 __ j(not_equal, &slow, not_taken); // do not leave holes in the array
377 __ sar(ebx, kSmiTagSize); // untag
378 __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset));
379 __ j(above_equal, &slow, not_taken);
380 // Restore tag and increment.
381 __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize));
382 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx);
383 __ sub(Operand(ebx), Immediate(1 << kSmiTagSize)); // decrement ebx again
384 __ jmp(&fast);
385
386
387 // Array case: Get the length and the elements array from the JS
388 // array. Check that the array is in fast mode; if it is the
389 // length is always a smi.
390 __ bind(&array);
391 // eax: value
392 // edx: JSArray
393 // ebx: index (as a smi)
394 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
395 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
396 Immediate(Factory::hash_table_map()));
397 __ j(equal, &slow, not_taken);
398
399 // Check the key against the length in the array, compute the
400 // address to store into and fall through to fast case.
401 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset));
402 __ j(above_equal, &extra, not_taken);
403
404
405 // Fast case: Do the store.
406 __ bind(&fast);
407 // eax: value
408 // ecx: FixedArray
409 // ebx: index (as a smi)
410 __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax);
411 // Update write barrier for the elements array address.
412 __ mov(edx, Operand(eax));
413 __ RecordWrite(ecx, 0, edx, ebx);
414 __ ret(0);
415 }
416
417
418 // Defined in ic.cc.
419 Object* CallIC_Miss(Arguments args);
420
421 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
422 // ----------- S t a t e -------------
423 // -----------------------------------
424 Label number, non_number, non_string, boolean, probe, miss;
425
426 // Get the receiver of the function from the stack; 1 ~ return address.
427 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
428 // Get the name of the function from the stack; 2 ~ return address, receiver
429 __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
430
431 // Probe the stub cache.
432 Code::Flags flags =
433 Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
434 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
435
436 // If the stub cache probing failed, the receiver might be a value.
437 // For value objects, we use the map of the prototype objects for
438 // the corresponding JSValue for the cache and that is what we need
439 // to probe.
440 //
441 // Check for number.
442 __ test(edx, Immediate(kSmiTagMask));
443 __ j(zero, &number, not_taken);
444 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
445 __ j(not_equal, &non_number, taken);
446 __ bind(&number);
447 StubCompiler::GenerateLoadGlobalFunctionPrototype(
448 masm, Context::NUMBER_FUNCTION_INDEX, edx);
449 __ jmp(&probe);
450
451 // Check for string.
452 __ bind(&non_number);
453 __ cmp(ebx, FIRST_NONSTRING_TYPE);
454 __ j(above_equal, &non_string, taken);
455 StubCompiler::GenerateLoadGlobalFunctionPrototype(
456 masm, Context::STRING_FUNCTION_INDEX, edx);
457 __ jmp(&probe);
458
459 // Check for boolean.
460 __ bind(&non_string);
461 __ cmp(edx, Factory::true_value());
462 __ j(equal, &boolean, not_taken);
463 __ cmp(edx, Factory::false_value());
464 __ j(not_equal, &miss, taken);
465 __ bind(&boolean);
466 StubCompiler::GenerateLoadGlobalFunctionPrototype(
467 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
468
469 // Probe the stub cache for the value object.
470 __ bind(&probe);
471 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
472
473 // Cache miss: Jump to runtime.
474 __ bind(&miss);
475 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
476 }
477
478
479 static void GenerateNormalHelper(MacroAssembler* masm,
480 int argc,
481 bool is_global_object,
482 Label* miss) {
483 // Search dictionary - put result in register edx.
484 GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx);
485
486 // Move the result to register edi and check that it isn't a smi.
487 __ mov(edi, Operand(edx));
488 __ test(edx, Immediate(kSmiTagMask));
489 __ j(zero, miss, not_taken);
490
491 // Check that the value is a JavaScript function.
492 __ CmpObjectType(edx, JS_FUNCTION_TYPE, edx);
493 __ j(not_equal, miss, not_taken);
494
495 // Check that the function has been loaded.
496 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
497 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kLazyLoadDataOffset));
498 __ cmp(edx, Factory::undefined_value());
499 __ j(not_equal, miss, not_taken);
500
501 // Patch the receiver with the global proxy if necessary.
502 if (is_global_object) {
503 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
504 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
505 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
506 }
507
508 // Invoke the function.
509 ParameterCount actual(argc);
510 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
511 }
512
513
514 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
515 // ----------- S t a t e -------------
516 // -----------------------------------
517
518 Label miss, global_object, non_global_object;
519
520 // Get the receiver of the function from the stack; 1 ~ return address.
521 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
522 // Get the name of the function from the stack; 2 ~ return address, receiver.
523 __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
524
525 // Check that the receiver isn't a smi.
526 __ test(edx, Immediate(kSmiTagMask));
527 __ j(zero, &miss, not_taken);
528
529 // Check that the receiver is a valid JS object.
530 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
531 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
532 __ cmp(eax, FIRST_JS_OBJECT_TYPE);
533 __ j(less, &miss, not_taken);
534
535 // If this assert fails, we have to check upper bound too.
536 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
537
538 // Check for access to global object.
539 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
540 __ j(equal, &global_object);
541 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
542 __ j(not_equal, &non_global_object);
543
544 // Accessing global object: Load and invoke.
545 __ bind(&global_object);
546 // Check that the global object does not require access checks.
547 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
548 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
549 __ j(not_equal, &miss, not_taken);
550 GenerateNormalHelper(masm, argc, true, &miss);
551
552 // Accessing non-global object: Check for access to global proxy.
553 Label global_proxy, invoke;
554 __ bind(&non_global_object);
555 __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
556 __ j(equal, &global_proxy, not_taken);
557 // Check that the non-global, non-global-proxy object does not
558 // require access checks.
559 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
560 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
561 __ j(not_equal, &miss, not_taken);
562 __ bind(&invoke);
563 GenerateNormalHelper(masm, argc, false, &miss);
564
565 // Global object proxy access: Check access rights.
566 __ bind(&global_proxy);
567 __ CheckAccessGlobalProxy(edx, eax, &miss);
568 __ jmp(&invoke);
569
570 // Cache miss: Jump to runtime.
571 __ bind(&miss);
572 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
573 }
574
575
576 void CallIC::Generate(MacroAssembler* masm,
577 int argc,
578 const ExternalReference& f) {
579 // ----------- S t a t e -------------
580 // -----------------------------------
581
582 // Get the receiver of the function from the stack; 1 ~ return address.
583 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
584 // Get the name of the function to call from the stack.
585 // 2 ~ receiver, return address.
586 __ mov(ebx, Operand(esp, (argc + 2) * kPointerSize));
587
588 // Enter an internal frame.
589 __ EnterInternalFrame();
590
591 // Push the receiver and the name of the function.
592 __ push(edx);
593 __ push(ebx);
594
595 // Call the entry.
596 CEntryStub stub;
597 __ mov(eax, Immediate(2));
598 __ mov(ebx, Immediate(f));
599 __ CallStub(&stub);
600
601 // Move result to edi and exit the internal frame.
602 __ mov(edi, eax);
603 __ LeaveInternalFrame();
604
605 // Check if the receiver is a global object of some sort.
606 Label invoke, global;
607 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
608 __ test(edx, Immediate(kSmiTagMask));
609 __ j(zero, &invoke, not_taken);
610 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
611 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
612 __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE);
613 __ j(equal, &global);
614 __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE);
615 __ j(not_equal, &invoke);
616
617 // Patch the receiver on the stack.
618 __ bind(&global);
619 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
620 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
621
622 // Invoke the function.
623 ParameterCount actual(argc);
624 __ bind(&invoke);
625 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
626 }
627
628
629 // Defined in ic.cc.
630 Object* LoadIC_Miss(Arguments args);
631
632 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
633 // ----------- S t a t e -------------
634 // -- ecx : name
635 // -- esp[0] : return address
636 // -- esp[4] : receiver
637 // -----------------------------------
638
639 __ mov(eax, Operand(esp, kPointerSize));
640
641 // Probe the stub cache.
642 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
643 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx);
644
645 // Cache miss: Jump to runtime.
646 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
647 }
648
649
650 void LoadIC::GenerateNormal(MacroAssembler* masm) {
651 // ----------- S t a t e -------------
652 // -- ecx : name
653 // -- esp[0] : return address
654 // -- esp[4] : receiver
655 // -----------------------------------
656
657 Label miss, probe, global;
658
659 __ mov(eax, Operand(esp, kPointerSize));
660
661 // Check that the receiver isn't a smi.
662 __ test(eax, Immediate(kSmiTagMask));
663 __ j(zero, &miss, not_taken);
664
665 // Check that the receiver is a valid JS object.
666 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
667 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset));
668 __ cmp(edx, FIRST_JS_OBJECT_TYPE);
669 __ j(less, &miss, not_taken);
670
671 // If this assert fails, we have to check upper bound too.
672 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
673
674 // Check for access to global object (unlikely).
675 __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
676 __ j(equal, &global, not_taken);
677
678 // Check for non-global object that requires access check.
679 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
680 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
681 __ j(not_zero, &miss, not_taken);
682
683 // Search the dictionary placing the result in eax.
684 __ bind(&probe);
685 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
686 GenerateCheckNonFunctionOrLoaded(masm, &miss, eax, edx);
687 __ ret(0);
688
689 // Global object access: Check access rights.
690 __ bind(&global);
691 __ CheckAccessGlobalProxy(eax, edx, &miss);
692 __ jmp(&probe);
693
694 // Cache miss: Restore receiver from stack and jump to runtime.
695 __ bind(&miss);
696 __ mov(eax, Operand(esp, 1 * kPointerSize));
697 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
698 }
699
700
701 void LoadIC::GenerateMiss(MacroAssembler* masm) {
702 // ----------- S t a t e -------------
703 // -- ecx : name
704 // -- esp[0] : return address
705 // -- esp[4] : receiver
706 // -----------------------------------
707
708 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
709 }
710
711
712 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
713 // ----------- S t a t e -------------
714 // -- ecx : name
715 // -- esp[0] : return address
716 // -- esp[4] : receiver
717 // -----------------------------------
718
719 __ mov(eax, Operand(esp, kPointerSize));
720
721 // Move the return address below the arguments.
722 __ pop(ebx);
723 __ push(eax);
724 __ push(ecx);
725 __ push(ebx);
726
727 // Perform tail call to the entry.
728 __ TailCallRuntime(f, 2);
729 }
730
731
732 // One byte opcode for test eax,0xXXXXXXXX.
733 static const byte kTestEaxByte = 0xA9;
734
735
736 bool KeyedLoadIC::HasInlinedVersion(Address address) {
737 Address test_instruction_address = address + 4; // 4 = stub address
738 return *test_instruction_address == kTestEaxByte;
739 }
740
741
742 void KeyedLoadIC::ClearInlinedVersion(Address address) {
743 // Insert null as the map to check for to make sure the map check fails
744 // sending control flow to the IC instead of the inlined version.
745 PatchInlinedMapCheck(address, Heap::null_value());
746 }
747
748
749 void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) {
750 Address test_instruction_address = address + 4; // 4 = stub address
751 // The keyed load has a fast inlined case if the IC call instruction
752 // is immediately followed by a test instruction.
753 if (*test_instruction_address == kTestEaxByte) {
754 // Fetch the offset from the test instruction to the map cmp
755 // instruction. This offset is stored in the last 4 bytes of the
756 // 5 byte test instruction.
757 Address offset_address = test_instruction_address + 1;
758 int offset_value = *(reinterpret_cast<int*>(offset_address));
759 // Compute the map address. The map address is in the last 4
760 // bytes of the 7-byte operand-immediate compare instruction, so
761 // we add 3 to the offset to get the map address.
762 Address map_address = test_instruction_address + offset_value + 3;
763 // Patch the map check.
764 (*(reinterpret_cast<Object**>(map_address))) = value;
765 }
766 }
767
768
769 // Defined in ic.cc.
770 Object* KeyedLoadIC_Miss(Arguments args);
771
772
773 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
774 // ----------- S t a t e -------------
775 // -- esp[0] : return address
776 // -- esp[4] : name
777 // -- esp[8] : receiver
778 // -----------------------------------
779
780 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
781 }
782
783
784 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
785 // ----------- S t a t e -------------
786 // -- esp[0] : return address
787 // -- esp[4] : name
788 // -- esp[8] : receiver
789 // -----------------------------------
790
791 __ mov(eax, Operand(esp, kPointerSize));
792 __ mov(ecx, Operand(esp, 2 * kPointerSize));
793
794 // Move the return address below the arguments.
795 __ pop(ebx);
796 __ push(ecx);
797 __ push(eax);
798 __ push(ebx);
799
800 // Perform tail call to the entry.
801 __ TailCallRuntime(f, 2);
802 }
803
804
805 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
806 // ----------- S t a t e -------------
807 // -- eax : value
808 // -- ecx : name
809 // -- esp[0] : return address
810 // -- esp[4] : receiver
811 // -----------------------------------
812
813 // Get the receiver from the stack and probe the stub cache.
814 __ mov(edx, Operand(esp, 4));
815 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
816 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
817
818 // Cache miss: Jump to runtime.
819 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
820 }
821
822
823 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
824 // ----------- S t a t e -------------
825 // -- eax : value
826 // -- ecx : transition map
827 // -- esp[0] : return address
828 // -- esp[4] : receiver
829 // -----------------------------------
830
831 // Move the return address below the arguments.
832 __ pop(ebx);
833 __ push(Operand(esp, 0));
834 __ push(ecx);
835 __ push(eax);
836 __ push(ebx);
837 // Perform tail call to the entry.
838 __ TailCallRuntime(
839 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
840 }
841
842
843 void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
844 // ----------- S t a t e -------------
845 // -- eax : value
846 // -- ecx : name
847 // -- esp[0] : return address
848 // -- esp[4] : receiver
849 // -----------------------------------
850
851 // Move the return address below the arguments.
852 __ pop(ebx);
853 __ push(Operand(esp, 0));
854 __ push(ecx);
855 __ push(eax);
856 __ push(ebx);
857
858 // Perform tail call to the entry.
859 __ TailCallRuntime(f, 3);
860 }
861
862
863 // Defined in ic.cc.
864 Object* KeyedStoreIC_Miss(Arguments args);
865
866 void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
867 // ----------- S t a t e -------------
868 // -- eax : value
869 // -- esp[0] : return address
870 // -- esp[4] : key
871 // -- esp[8] : receiver
872 // -----------------------------------
873
874 // Move the return address below the arguments.
875 __ pop(ecx);
876 __ push(Operand(esp, 1 * kPointerSize));
877 __ push(Operand(esp, 1 * kPointerSize));
878 __ push(eax);
879 __ push(ecx);
880
881 // Do tail-call to runtime routine.
882 __ TailCallRuntime(f, 3);
883 }
884
885
886 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
887 // ----------- S t a t e -------------
888 // -- eax : value
889 // -- ecx : transition map
890 // -- esp[0] : return address
891 // -- esp[4] : key
892 // -- esp[8] : receiver
893 // -----------------------------------
894
895 // Move the return address below the arguments.
896 __ pop(ebx);
897 __ push(Operand(esp, 1 * kPointerSize));
898 __ push(ecx);
899 __ push(eax);
900 __ push(ebx);
901
902 // Do tail-call to runtime routine.
903 __ TailCallRuntime(
904 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
905 }
906
907 #undef __
908
909
910 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/frames-ia32.cc ('k') | src/ia32/jump-target-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698