OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "ic-inl.h" | 32 #include "ic-inl.h" |
33 #include "codegen-inl.h" | 33 #include "codegen-inl.h" |
34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
35 | 35 |
36 namespace v8 { | 36 namespace v8 { |
37 namespace internal { | 37 namespace internal { |
38 | 38 |
39 #define __ ACCESS_MASM(masm) | 39 #define __ ACCESS_MASM(masm) |
40 | 40 |
41 | 41 |
42 static void ProbeTable(MacroAssembler* masm, | 42 static void ProbeTable(Isolate* isolate, |
| 43 MacroAssembler* masm, |
43 Code::Flags flags, | 44 Code::Flags flags, |
44 StubCache::Table table, | 45 StubCache::Table table, |
45 Register name, | 46 Register name, |
46 Register offset, | 47 Register offset, |
47 Register extra) { | 48 Register extra) { |
48 ExternalReference key_offset(SCTableReference::keyReference(table)); | 49 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |
49 ExternalReference value_offset(SCTableReference::valueReference(table)); | 50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
50 | 51 |
51 Label miss; | 52 Label miss; |
52 | 53 |
53 if (extra.is_valid()) { | 54 if (extra.is_valid()) { |
54 // Get the code entry from the cache. | 55 // Get the code entry from the cache. |
55 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); | 56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); |
56 | 57 |
57 // Check that the key in the entry matches the name. | 58 // Check that the key in the entry matches the name. |
58 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); | 59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); |
59 __ j(not_equal, &miss, not_taken); | 60 __ j(not_equal, &miss, not_taken); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
107 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
108 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
109 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
110 Label* miss_label, | 111 Label* miss_label, |
111 Register receiver, | 112 Register receiver, |
112 String* name, | 113 String* name, |
113 Register r0, | 114 Register r0, |
114 Register r1) { | 115 Register r1) { |
115 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
116 __ IncrementCounter(&Counters::negative_lookups, 1); | 117 __ IncrementCounter(COUNTERS->negative_lookups(), 1); |
117 __ IncrementCounter(&Counters::negative_lookups_miss, 1); | 118 __ IncrementCounter(COUNTERS->negative_lookups_miss(), 1); |
118 | 119 |
119 Label done; | 120 Label done; |
120 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
121 | 122 |
122 const int kInterceptorOrAccessCheckNeededMask = | 123 const int kInterceptorOrAccessCheckNeededMask = |
123 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
124 | 125 |
125 // Bail out if the receiver has a named interceptor or requires access checks. | 126 // Bail out if the receiver has a named interceptor or requires access checks. |
126 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
127 kInterceptorOrAccessCheckNeededMask); | 128 kInterceptorOrAccessCheckNeededMask); |
128 __ j(not_zero, miss_label, not_taken); | 129 __ j(not_zero, miss_label, not_taken); |
129 | 130 |
130 // Check that receiver is a JSObject. | 131 // Check that receiver is a JSObject. |
131 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); | 132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); |
132 __ j(below, miss_label, not_taken); | 133 __ j(below, miss_label, not_taken); |
133 | 134 |
134 // Load properties array. | 135 // Load properties array. |
135 Register properties = r0; | 136 Register properties = r0; |
136 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
137 | 138 |
138 // Check that the properties array is a dictionary. | 139 // Check that the properties array is a dictionary. |
139 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
140 Immediate(Factory::hash_table_map())); | 141 Immediate(FACTORY->hash_table_map())); |
141 __ j(not_equal, miss_label); | 142 __ j(not_equal, miss_label); |
142 | 143 |
143 // Compute the capacity mask. | 144 // Compute the capacity mask. |
144 const int kCapacityOffset = | 145 const int kCapacityOffset = |
145 StringDictionary::kHeaderSize + | 146 StringDictionary::kHeaderSize + |
146 StringDictionary::kCapacityIndex * kPointerSize; | 147 StringDictionary::kCapacityIndex * kPointerSize; |
147 | 148 |
148 // Generate an unrolled loop that performs a few probes before | 149 // Generate an unrolled loop that performs a few probes before |
149 // giving up. | 150 // giving up. |
150 static const int kProbes = 4; | 151 static const int kProbes = 4; |
(...skipping 19 matching lines...) Expand all Loading... |
170 | 171 |
171 // Scale the index by multiplying by the entry size. | 172 // Scale the index by multiplying by the entry size. |
172 ASSERT(StringDictionary::kEntrySize == 3); | 173 ASSERT(StringDictionary::kEntrySize == 3); |
173 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. | 174 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
174 | 175 |
175 Register entity_name = r1; | 176 Register entity_name = r1; |
176 // Having undefined at this place means the name is not contained. | 177 // Having undefined at this place means the name is not contained. |
177 ASSERT_EQ(kSmiTagSize, 1); | 178 ASSERT_EQ(kSmiTagSize, 1); |
178 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, | 179 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, |
179 kElementsStartOffset - kHeapObjectTag)); | 180 kElementsStartOffset - kHeapObjectTag)); |
180 __ cmp(entity_name, Factory::undefined_value()); | 181 __ cmp(entity_name, FACTORY->undefined_value()); |
181 if (i != kProbes - 1) { | 182 if (i != kProbes - 1) { |
182 __ j(equal, &done, taken); | 183 __ j(equal, &done, taken); |
183 | 184 |
184 // Stop if found the property. | 185 // Stop if found the property. |
185 __ cmp(entity_name, Handle<String>(name)); | 186 __ cmp(entity_name, Handle<String>(name)); |
186 __ j(equal, miss_label, not_taken); | 187 __ j(equal, miss_label, not_taken); |
187 | 188 |
188 // Check if the entry name is not a symbol. | 189 // Check if the entry name is not a symbol. |
189 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); | 190 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
190 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 191 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
191 kIsSymbolMask); | 192 kIsSymbolMask); |
192 __ j(zero, miss_label, not_taken); | 193 __ j(zero, miss_label, not_taken); |
193 } else { | 194 } else { |
194 // Give up probing if still not found the undefined value. | 195 // Give up probing if still not found the undefined value. |
195 __ j(not_equal, miss_label, not_taken); | 196 __ j(not_equal, miss_label, not_taken); |
196 } | 197 } |
197 } | 198 } |
198 | 199 |
199 __ bind(&done); | 200 __ bind(&done); |
200 __ DecrementCounter(&Counters::negative_lookups_miss, 1); | 201 __ DecrementCounter(COUNTERS->negative_lookups_miss(), 1); |
201 } | 202 } |
202 | 203 |
203 | 204 |
204 void StubCache::GenerateProbe(MacroAssembler* masm, | 205 void StubCache::GenerateProbe(MacroAssembler* masm, |
205 Code::Flags flags, | 206 Code::Flags flags, |
206 Register receiver, | 207 Register receiver, |
207 Register name, | 208 Register name, |
208 Register scratch, | 209 Register scratch, |
209 Register extra, | 210 Register extra, |
210 Register extra2) { | 211 Register extra2) { |
| 212 Isolate* isolate = Isolate::Current(); |
211 Label miss; | 213 Label miss; |
212 USE(extra2); // The register extra2 is not used on the ia32 platform. | 214 USE(extra2); // The register extra2 is not used on the ia32 platform. |
213 | 215 |
214 // Make sure that code is valid. The shifting code relies on the | 216 // Make sure that code is valid. The shifting code relies on the |
215 // entry size being 8. | 217 // entry size being 8. |
216 ASSERT(sizeof(Entry) == 8); | 218 ASSERT(sizeof(Entry) == 8); |
217 | 219 |
218 // Make sure the flags does not name a specific type. | 220 // Make sure the flags does not name a specific type. |
219 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 221 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
220 | 222 |
(...skipping 12 matching lines...) Expand all Loading... |
233 __ test(receiver, Immediate(kSmiTagMask)); | 235 __ test(receiver, Immediate(kSmiTagMask)); |
234 __ j(zero, &miss, not_taken); | 236 __ j(zero, &miss, not_taken); |
235 | 237 |
236 // Get the map of the receiver and compute the hash. | 238 // Get the map of the receiver and compute the hash. |
237 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 239 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
238 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 240 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
239 __ xor_(scratch, flags); | 241 __ xor_(scratch, flags); |
240 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 242 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
241 | 243 |
242 // Probe the primary table. | 244 // Probe the primary table. |
243 ProbeTable(masm, flags, kPrimary, name, scratch, extra); | 245 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
244 | 246 |
245 // Primary miss: Compute hash for secondary probe. | 247 // Primary miss: Compute hash for secondary probe. |
246 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 248 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
247 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 249 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
248 __ xor_(scratch, flags); | 250 __ xor_(scratch, flags); |
249 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 251 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
250 __ sub(scratch, Operand(name)); | 252 __ sub(scratch, Operand(name)); |
251 __ add(Operand(scratch), Immediate(flags)); | 253 __ add(Operand(scratch), Immediate(flags)); |
252 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); | 254 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); |
253 | 255 |
254 // Probe the secondary table. | 256 // Probe the secondary table. |
255 ProbeTable(masm, flags, kSecondary, name, scratch, extra); | 257 ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra); |
256 | 258 |
257 // Cache miss: Fall-through and let caller handle the miss by | 259 // Cache miss: Fall-through and let caller handle the miss by |
258 // entering the runtime system. | 260 // entering the runtime system. |
259 __ bind(&miss); | 261 __ bind(&miss); |
260 } | 262 } |
261 | 263 |
262 | 264 |
263 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 265 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
264 int index, | 266 int index, |
265 Register prototype) { | 267 Register prototype) { |
266 __ LoadGlobalFunction(index, prototype); | 268 __ LoadGlobalFunction(index, prototype); |
267 __ LoadGlobalFunctionInitialMap(prototype, prototype); | 269 __ LoadGlobalFunctionInitialMap(prototype, prototype); |
268 // Load the prototype from the initial map. | 270 // Load the prototype from the initial map. |
269 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 271 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
270 } | 272 } |
271 | 273 |
272 | 274 |
273 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 275 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
274 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 276 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
275 // Check we're still in the same context. | 277 // Check we're still in the same context. |
276 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 278 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
277 Top::global()); | 279 Isolate::Current()->global()); |
278 __ j(not_equal, miss); | 280 __ j(not_equal, miss); |
279 // Get the global function with the given index. | 281 // Get the global function with the given index. |
280 JSFunction* function = JSFunction::cast(Top::global_context()->get(index)); | 282 JSFunction* function = JSFunction::cast( |
| 283 Isolate::Current()->global_context()->get(index)); |
281 // Load its initial map. The global functions all have initial maps. | 284 // Load its initial map. The global functions all have initial maps. |
282 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); | 285 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); |
283 // Load the prototype from the initial map. | 286 // Load the prototype from the initial map. |
284 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 287 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
285 } | 288 } |
286 | 289 |
287 | 290 |
288 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 291 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
289 Register receiver, | 292 Register receiver, |
290 Register scratch, | 293 Register scratch, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 } | 391 } |
389 | 392 |
390 | 393 |
391 static void PushInterceptorArguments(MacroAssembler* masm, | 394 static void PushInterceptorArguments(MacroAssembler* masm, |
392 Register receiver, | 395 Register receiver, |
393 Register holder, | 396 Register holder, |
394 Register name, | 397 Register name, |
395 JSObject* holder_obj) { | 398 JSObject* holder_obj) { |
396 __ push(name); | 399 __ push(name); |
397 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 400 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
398 ASSERT(!Heap::InNewSpace(interceptor)); | 401 ASSERT(!HEAP->InNewSpace(interceptor)); |
399 Register scratch = name; | 402 Register scratch = name; |
400 __ mov(scratch, Immediate(Handle<Object>(interceptor))); | 403 __ mov(scratch, Immediate(Handle<Object>(interceptor))); |
401 __ push(scratch); | 404 __ push(scratch); |
402 __ push(receiver); | 405 __ push(receiver); |
403 __ push(holder); | 406 __ push(holder); |
404 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); | 407 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); |
405 } | 408 } |
406 | 409 |
407 | 410 |
408 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 411 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 // ----------------------------------- | 476 // ----------------------------------- |
474 // Get the function and setup the context. | 477 // Get the function and setup the context. |
475 JSFunction* function = optimization.constant_function(); | 478 JSFunction* function = optimization.constant_function(); |
476 __ mov(edi, Immediate(Handle<JSFunction>(function))); | 479 __ mov(edi, Immediate(Handle<JSFunction>(function))); |
477 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 480 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
478 | 481 |
479 // Pass the additional arguments. | 482 // Pass the additional arguments. |
480 __ mov(Operand(esp, 2 * kPointerSize), edi); | 483 __ mov(Operand(esp, 2 * kPointerSize), edi); |
481 Object* call_data = optimization.api_call_info()->data(); | 484 Object* call_data = optimization.api_call_info()->data(); |
482 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 485 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
483 if (Heap::InNewSpace(call_data)) { | 486 if (HEAP->InNewSpace(call_data)) { |
484 __ mov(ecx, api_call_info_handle); | 487 __ mov(ecx, api_call_info_handle); |
485 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 488 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
486 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 489 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
487 } else { | 490 } else { |
488 __ mov(Operand(esp, 3 * kPointerSize), | 491 __ mov(Operand(esp, 3 * kPointerSize), |
489 Immediate(Handle<Object>(call_data))); | 492 Immediate(Handle<Object>(call_data))); |
490 } | 493 } |
491 | 494 |
492 // Prepare arguments. | 495 // Prepare arguments. |
493 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 496 __ lea(eax, Operand(esp, 3 * kPointerSize)); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 } else { | 570 } else { |
568 CompileRegular(masm, | 571 CompileRegular(masm, |
569 object, | 572 object, |
570 receiver, | 573 receiver, |
571 scratch1, | 574 scratch1, |
572 scratch2, | 575 scratch2, |
573 scratch3, | 576 scratch3, |
574 name, | 577 name, |
575 holder, | 578 holder, |
576 miss); | 579 miss); |
577 return Heap::undefined_value(); // Success. | 580 return HEAP->undefined_value(); // Success. |
578 } | 581 } |
579 } | 582 } |
580 | 583 |
581 private: | 584 private: |
582 MaybeObject* CompileCacheable(MacroAssembler* masm, | 585 MaybeObject* CompileCacheable(MacroAssembler* masm, |
583 JSObject* object, | 586 JSObject* object, |
584 Register receiver, | 587 Register receiver, |
585 Register scratch1, | 588 Register scratch1, |
586 Register scratch2, | 589 Register scratch2, |
587 Register scratch3, | 590 Register scratch3, |
(...skipping 15 matching lines...) Expand all Loading... |
603 interceptor_holder); | 606 interceptor_holder); |
604 if (depth1 == kInvalidProtoDepth) { | 607 if (depth1 == kInvalidProtoDepth) { |
605 depth2 = | 608 depth2 = |
606 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 609 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, |
607 lookup->holder()); | 610 lookup->holder()); |
608 } | 611 } |
609 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | 612 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || |
610 (depth2 != kInvalidProtoDepth); | 613 (depth2 != kInvalidProtoDepth); |
611 } | 614 } |
612 | 615 |
613 __ IncrementCounter(&Counters::call_const_interceptor, 1); | 616 __ IncrementCounter(COUNTERS->call_const_interceptor(), 1); |
614 | 617 |
615 if (can_do_fast_api_call) { | 618 if (can_do_fast_api_call) { |
616 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); | 619 __ IncrementCounter(COUNTERS->call_const_interceptor_fast_api(), 1); |
617 ReserveSpaceForFastApiCall(masm, scratch1); | 620 ReserveSpaceForFastApiCall(masm, scratch1); |
618 } | 621 } |
619 | 622 |
620 // Check that the maps from receiver to interceptor's holder | 623 // Check that the maps from receiver to interceptor's holder |
621 // haven't changed and thus we can invoke interceptor. | 624 // haven't changed and thus we can invoke interceptor. |
622 Label miss_cleanup; | 625 Label miss_cleanup; |
623 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 626 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
624 Register holder = | 627 Register holder = |
625 stub_compiler_->CheckPrototypes(object, receiver, | 628 stub_compiler_->CheckPrototypes(object, receiver, |
626 interceptor_holder, scratch1, | 629 interceptor_holder, scratch1, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 FreeSpaceForFastApiCall(masm, scratch1); | 668 FreeSpaceForFastApiCall(masm, scratch1); |
666 __ jmp(miss_label); | 669 __ jmp(miss_label); |
667 } | 670 } |
668 | 671 |
669 // Invoke a regular function. | 672 // Invoke a regular function. |
670 __ bind(®ular_invoke); | 673 __ bind(®ular_invoke); |
671 if (can_do_fast_api_call) { | 674 if (can_do_fast_api_call) { |
672 FreeSpaceForFastApiCall(masm, scratch1); | 675 FreeSpaceForFastApiCall(masm, scratch1); |
673 } | 676 } |
674 | 677 |
675 return Heap::undefined_value(); // Success. | 678 return HEAP->undefined_value(); // Success. |
676 } | 679 } |
677 | 680 |
678 void CompileRegular(MacroAssembler* masm, | 681 void CompileRegular(MacroAssembler* masm, |
679 JSObject* object, | 682 JSObject* object, |
680 Register receiver, | 683 Register receiver, |
681 Register scratch1, | 684 Register scratch1, |
682 Register scratch2, | 685 Register scratch2, |
683 Register scratch3, | 686 Register scratch3, |
684 String* name, | 687 String* name, |
685 JSObject* interceptor_holder, | 688 JSObject* interceptor_holder, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 CompileCallLoadPropertyWithInterceptor(masm, | 724 CompileCallLoadPropertyWithInterceptor(masm, |
722 receiver, | 725 receiver, |
723 holder, | 726 holder, |
724 name_, | 727 name_, |
725 holder_obj); | 728 holder_obj); |
726 | 729 |
727 __ pop(name_); // Restore the name. | 730 __ pop(name_); // Restore the name. |
728 __ pop(receiver); // Restore the holder. | 731 __ pop(receiver); // Restore the holder. |
729 __ LeaveInternalFrame(); | 732 __ LeaveInternalFrame(); |
730 | 733 |
731 __ cmp(eax, Factory::no_interceptor_result_sentinel()); | 734 __ cmp(eax, FACTORY->no_interceptor_result_sentinel()); |
732 __ j(not_equal, interceptor_succeeded); | 735 __ j(not_equal, interceptor_succeeded); |
733 } | 736 } |
734 | 737 |
735 StubCompiler* stub_compiler_; | 738 StubCompiler* stub_compiler_; |
736 const ParameterCount& arguments_; | 739 const ParameterCount& arguments_; |
737 Register name_; | 740 Register name_; |
738 }; | 741 }; |
739 | 742 |
740 | 743 |
741 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 744 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
742 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 745 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
743 Code* code = NULL; | 746 Code* code = NULL; |
744 if (kind == Code::LOAD_IC) { | 747 if (kind == Code::LOAD_IC) { |
745 code = Builtins::builtin(Builtins::LoadIC_Miss); | 748 code = Isolate::Current()->builtins()->builtin(Builtins::LoadIC_Miss); |
746 } else { | 749 } else { |
747 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); | 750 code = Isolate::Current()->builtins()->builtin(Builtins::KeyedLoadIC_Miss); |
748 } | 751 } |
749 | 752 |
750 Handle<Code> ic(code); | 753 Handle<Code> ic(code); |
751 __ jmp(ic, RelocInfo::CODE_TARGET); | 754 __ jmp(ic, RelocInfo::CODE_TARGET); |
752 } | 755 } |
753 | 756 |
754 | 757 |
755 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 758 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
756 // but may be destroyed if store is successful. | 759 // but may be destroyed if store is successful. |
757 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 760 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 Label* miss) { | 847 Label* miss) { |
845 Object* probe; | 848 Object* probe; |
846 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 849 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
847 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 850 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
848 } | 851 } |
849 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 852 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
850 ASSERT(cell->value()->IsTheHole()); | 853 ASSERT(cell->value()->IsTheHole()); |
851 if (Serializer::enabled()) { | 854 if (Serializer::enabled()) { |
852 __ mov(scratch, Immediate(Handle<Object>(cell))); | 855 __ mov(scratch, Immediate(Handle<Object>(cell))); |
853 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 856 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
854 Immediate(Factory::the_hole_value())); | 857 Immediate(FACTORY->the_hole_value())); |
855 } else { | 858 } else { |
856 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 859 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
857 Immediate(Factory::the_hole_value())); | 860 Immediate(FACTORY->the_hole_value())); |
858 } | 861 } |
859 __ j(not_equal, miss, not_taken); | 862 __ j(not_equal, miss, not_taken); |
860 return cell; | 863 return cell; |
861 } | 864 } |
862 | 865 |
863 | 866 |
864 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 867 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
865 // from object to (but not including) holder. | 868 // from object to (but not including) holder. |
866 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 869 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( |
867 MacroAssembler* masm, | 870 MacroAssembler* masm, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 // Only global objects and objects that do not require access | 926 // Only global objects and objects that do not require access |
924 // checks are allowed in stubs. | 927 // checks are allowed in stubs. |
925 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 928 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
926 | 929 |
927 ASSERT(current->GetPrototype()->IsJSObject()); | 930 ASSERT(current->GetPrototype()->IsJSObject()); |
928 JSObject* prototype = JSObject::cast(current->GetPrototype()); | 931 JSObject* prototype = JSObject::cast(current->GetPrototype()); |
929 if (!current->HasFastProperties() && | 932 if (!current->HasFastProperties() && |
930 !current->IsJSGlobalObject() && | 933 !current->IsJSGlobalObject() && |
931 !current->IsJSGlobalProxy()) { | 934 !current->IsJSGlobalProxy()) { |
932 if (!name->IsSymbol()) { | 935 if (!name->IsSymbol()) { |
933 MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name); | 936 MaybeObject* maybe_lookup_result = HEAP->LookupSymbol(name); |
934 Object* lookup_result = NULL; // Initialization to please compiler. | 937 Object* lookup_result = NULL; // Initialization to please compiler. |
935 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 938 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
936 set_failure(Failure::cast(maybe_lookup_result)); | 939 set_failure(Failure::cast(maybe_lookup_result)); |
937 return reg; | 940 return reg; |
938 } | 941 } |
939 name = String::cast(lookup_result); | 942 name = String::cast(lookup_result); |
940 } | 943 } |
941 ASSERT(current->property_dictionary()->FindEntry(name) == | 944 ASSERT(current->property_dictionary()->FindEntry(name) == |
942 StringDictionary::kNotFound); | 945 StringDictionary::kNotFound); |
943 | 946 |
944 GenerateDictionaryNegativeLookup(masm(), | 947 GenerateDictionaryNegativeLookup(masm(), |
945 miss, | 948 miss, |
946 reg, | 949 reg, |
947 name, | 950 name, |
948 scratch1, | 951 scratch1, |
949 scratch2); | 952 scratch2); |
950 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 953 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
951 reg = holder_reg; // from now the object is in holder_reg | 954 reg = holder_reg; // from now the object is in holder_reg |
952 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 955 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
953 } else if (Heap::InNewSpace(prototype)) { | 956 } else if (HEAP->InNewSpace(prototype)) { |
954 // Get the map of the current object. | 957 // Get the map of the current object. |
955 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 958 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
956 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 959 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
957 // Branch on the result of the map check. | 960 // Branch on the result of the map check. |
958 __ j(not_equal, miss, not_taken); | 961 __ j(not_equal, miss, not_taken); |
959 // Check access rights to the global object. This has to happen | 962 // Check access rights to the global object. This has to happen |
960 // after the map check so that we know that the object is | 963 // after the map check so that we know that the object is |
961 // actually a global object. | 964 // actually a global object. |
962 if (current->IsJSGlobalProxy()) { | 965 if (current->IsJSGlobalProxy()) { |
963 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 966 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
(...skipping 26 matching lines...) Expand all Loading... |
990 if (save_at_depth == depth) { | 993 if (save_at_depth == depth) { |
991 __ mov(Operand(esp, kPointerSize), reg); | 994 __ mov(Operand(esp, kPointerSize), reg); |
992 } | 995 } |
993 | 996 |
994 // Go to the next object in the prototype chain. | 997 // Go to the next object in the prototype chain. |
995 current = prototype; | 998 current = prototype; |
996 } | 999 } |
997 ASSERT(current == holder); | 1000 ASSERT(current == holder); |
998 | 1001 |
999 // Log the check depth. | 1002 // Log the check depth. |
1000 LOG(IntEvent("check-maps-depth", depth + 1)); | 1003 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1001 | 1004 |
1002 // Check the holder map. | 1005 // Check the holder map. |
1003 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1006 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
1004 Immediate(Handle<Map>(holder->map()))); | 1007 Immediate(Handle<Map>(holder->map()))); |
1005 __ j(not_equal, miss, not_taken); | 1008 __ j(not_equal, miss, not_taken); |
1006 | 1009 |
1007 // Perform security check for access to the global object. | 1010 // Perform security check for access to the global object. |
1008 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1011 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1009 if (holder->IsJSGlobalProxy()) { | 1012 if (holder->IsJSGlobalProxy()) { |
1010 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1013 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 | 1076 |
1074 // Insert additional parameters into the stack frame above return address. | 1077 // Insert additional parameters into the stack frame above return address. |
1075 ASSERT(!scratch3.is(reg)); | 1078 ASSERT(!scratch3.is(reg)); |
1076 __ pop(scratch3); // Get return address to place it below. | 1079 __ pop(scratch3); // Get return address to place it below. |
1077 | 1080 |
1078 __ push(receiver); // receiver | 1081 __ push(receiver); // receiver |
1079 __ mov(scratch2, Operand(esp)); | 1082 __ mov(scratch2, Operand(esp)); |
1080 ASSERT(!scratch2.is(reg)); | 1083 ASSERT(!scratch2.is(reg)); |
1081 __ push(reg); // holder | 1084 __ push(reg); // holder |
1082 // Push data from AccessorInfo. | 1085 // Push data from AccessorInfo. |
1083 if (Heap::InNewSpace(callback_handle->data())) { | 1086 if (HEAP->InNewSpace(callback_handle->data())) { |
1084 __ mov(scratch1, Immediate(callback_handle)); | 1087 __ mov(scratch1, Immediate(callback_handle)); |
1085 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 1088 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
1086 } else { | 1089 } else { |
1087 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 1090 __ push(Immediate(Handle<Object>(callback_handle->data()))); |
1088 } | 1091 } |
1089 | 1092 |
1090 // Save a pointer to where we pushed the arguments pointer. | 1093 // Save a pointer to where we pushed the arguments pointer. |
1091 // This will be passed as the const AccessorInfo& to the C++ callback. | 1094 // This will be passed as the const AccessorInfo& to the C++ callback. |
1092 __ push(scratch2); | 1095 __ push(scratch2); |
1093 | 1096 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 // of this method.) | 1200 // of this method.) |
1198 CompileCallLoadPropertyWithInterceptor(masm(), | 1201 CompileCallLoadPropertyWithInterceptor(masm(), |
1199 receiver, | 1202 receiver, |
1200 holder_reg, | 1203 holder_reg, |
1201 name_reg, | 1204 name_reg, |
1202 interceptor_holder); | 1205 interceptor_holder); |
1203 | 1206 |
1204 // Check if interceptor provided a value for property. If it's | 1207 // Check if interceptor provided a value for property. If it's |
1205 // the case, return immediately. | 1208 // the case, return immediately. |
1206 Label interceptor_failed; | 1209 Label interceptor_failed; |
1207 __ cmp(eax, Factory::no_interceptor_result_sentinel()); | 1210 __ cmp(eax, FACTORY->no_interceptor_result_sentinel()); |
1208 __ j(equal, &interceptor_failed); | 1211 __ j(equal, &interceptor_failed); |
1209 __ LeaveInternalFrame(); | 1212 __ LeaveInternalFrame(); |
1210 __ ret(0); | 1213 __ ret(0); |
1211 | 1214 |
1212 __ bind(&interceptor_failed); | 1215 __ bind(&interceptor_failed); |
1213 __ pop(name_reg); | 1216 __ pop(name_reg); |
1214 __ pop(holder_reg); | 1217 __ pop(holder_reg); |
1215 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1218 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1216 __ pop(receiver); | 1219 __ pop(receiver); |
1217 } | 1220 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 Label* miss) { | 1321 Label* miss) { |
1319 // Get the value from the cell. | 1322 // Get the value from the cell. |
1320 if (Serializer::enabled()) { | 1323 if (Serializer::enabled()) { |
1321 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1324 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1322 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1325 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1323 } else { | 1326 } else { |
1324 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1327 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
1325 } | 1328 } |
1326 | 1329 |
1327 // Check that the cell contains the same function. | 1330 // Check that the cell contains the same function. |
1328 if (Heap::InNewSpace(function)) { | 1331 if (HEAP->InNewSpace(function)) { |
1329 // We can't embed a pointer to a function in new space so we have | 1332 // We can't embed a pointer to a function in new space so we have |
1330 // to verify that the shared function info is unchanged. This has | 1333 // to verify that the shared function info is unchanged. This has |
1331 // the nice side effect that multiple closures based on the same | 1334 // the nice side effect that multiple closures based on the same |
1332 // function can all use this call IC. Before we load through the | 1335 // function can all use this call IC. Before we load through the |
1333 // function, we have to verify that it still is a function. | 1336 // function, we have to verify that it still is a function. |
1334 __ test(edi, Immediate(kSmiTagMask)); | 1337 __ test(edi, Immediate(kSmiTagMask)); |
1335 __ j(zero, miss, not_taken); | 1338 __ j(zero, miss, not_taken); |
1336 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1339 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1337 __ j(not_equal, miss, not_taken); | 1340 __ j(not_equal, miss, not_taken); |
1338 | 1341 |
1339 // Check the shared function info. Make sure it hasn't changed. | 1342 // Check the shared function info. Make sure it hasn't changed. |
1340 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1343 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1341 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1344 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1342 __ j(not_equal, miss, not_taken); | 1345 __ j(not_equal, miss, not_taken); |
1343 } else { | 1346 } else { |
1344 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1347 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1345 __ j(not_equal, miss, not_taken); | 1348 __ j(not_equal, miss, not_taken); |
1346 } | 1349 } |
1347 } | 1350 } |
1348 | 1351 |
1349 | 1352 |
1350 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1353 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
1351 MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(), | 1354 MaybeObject* maybe_obj = |
1352 kind_); | 1355 Isolate::Current()->stub_cache()->ComputeCallMiss( |
| 1356 arguments().immediate(), kind_); |
1353 Object* obj; | 1357 Object* obj; |
1354 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1358 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1355 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1359 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
1356 return obj; | 1360 return obj; |
1357 } | 1361 } |
1358 | 1362 |
1359 | 1363 |
1360 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1364 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( |
1361 JSObject* object, | 1365 JSObject* object, |
1362 JSObject* holder, | 1366 JSObject* holder, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1422 String* name) { | 1426 String* name) { |
1423 // ----------- S t a t e ------------- | 1427 // ----------- S t a t e ------------- |
1424 // -- ecx : name | 1428 // -- ecx : name |
1425 // -- esp[0] : return address | 1429 // -- esp[0] : return address |
1426 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1430 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1427 // -- ... | 1431 // -- ... |
1428 // -- esp[(argc + 1) * 4] : receiver | 1432 // -- esp[(argc + 1) * 4] : receiver |
1429 // ----------------------------------- | 1433 // ----------------------------------- |
1430 | 1434 |
1431 // If object is not an array, bail out to regular call. | 1435 // If object is not an array, bail out to regular call. |
1432 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); | 1436 if (!object->IsJSArray() || cell != NULL) return HEAP->undefined_value(); |
1433 | 1437 |
1434 Label miss; | 1438 Label miss; |
1435 | 1439 |
1436 GenerateNameCheck(name, &miss); | 1440 GenerateNameCheck(name, &miss); |
1437 | 1441 |
1438 // Get the receiver from the stack. | 1442 // Get the receiver from the stack. |
1439 const int argc = arguments().immediate(); | 1443 const int argc = arguments().immediate(); |
1440 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1444 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1441 | 1445 |
1442 // Check that the receiver isn't a smi. | 1446 // Check that the receiver isn't a smi. |
1443 __ test(edx, Immediate(kSmiTagMask)); | 1447 __ test(edx, Immediate(kSmiTagMask)); |
1444 __ j(zero, &miss); | 1448 __ j(zero, &miss); |
1445 | 1449 |
1446 CheckPrototypes(JSObject::cast(object), edx, | 1450 CheckPrototypes(JSObject::cast(object), edx, |
1447 holder, ebx, | 1451 holder, ebx, |
1448 eax, edi, name, &miss); | 1452 eax, edi, name, &miss); |
1449 | 1453 |
1450 if (argc == 0) { | 1454 if (argc == 0) { |
1451 // Noop, return the length. | 1455 // Noop, return the length. |
1452 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1456 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1453 __ ret((argc + 1) * kPointerSize); | 1457 __ ret((argc + 1) * kPointerSize); |
1454 } else { | 1458 } else { |
1455 Label call_builtin; | 1459 Label call_builtin; |
1456 | 1460 |
1457 // Get the elements array of the object. | 1461 // Get the elements array of the object. |
1458 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1462 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1459 | 1463 |
1460 // Check that the elements are in fast mode and writable. | 1464 // Check that the elements are in fast mode and writable. |
1461 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1465 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1462 Immediate(Factory::fixed_array_map())); | 1466 Immediate(FACTORY->fixed_array_map())); |
1463 __ j(not_equal, &call_builtin); | 1467 __ j(not_equal, &call_builtin); |
1464 | 1468 |
1465 if (argc == 1) { // Otherwise fall through to call builtin. | 1469 if (argc == 1) { // Otherwise fall through to call builtin. |
1466 Label exit, with_write_barrier, attempt_to_grow_elements; | 1470 Label exit, with_write_barrier, attempt_to_grow_elements; |
1467 | 1471 |
1468 // Get the array's length into eax and calculate new length. | 1472 // Get the array's length into eax and calculate new length. |
1469 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1473 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1470 STATIC_ASSERT(kSmiTagSize == 1); | 1474 STATIC_ASSERT(kSmiTagSize == 1); |
1471 STATIC_ASSERT(kSmiTag == 0); | 1475 STATIC_ASSERT(kSmiTag == 0); |
1472 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); | 1476 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1528 | 1532 |
1529 // We fit and could grow elements. | 1533 // We fit and could grow elements. |
1530 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); | 1534 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); |
1531 __ mov(ecx, Operand(esp, argc * kPointerSize)); | 1535 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
1532 | 1536 |
1533 // Push the argument... | 1537 // Push the argument... |
1534 __ mov(Operand(edx, 0), ecx); | 1538 __ mov(Operand(edx, 0), ecx); |
1535 // ... and fill the rest with holes. | 1539 // ... and fill the rest with holes. |
1536 for (int i = 1; i < kAllocationDelta; i++) { | 1540 for (int i = 1; i < kAllocationDelta; i++) { |
1537 __ mov(Operand(edx, i * kPointerSize), | 1541 __ mov(Operand(edx, i * kPointerSize), |
1538 Immediate(Factory::the_hole_value())); | 1542 Immediate(FACTORY->the_hole_value())); |
1539 } | 1543 } |
1540 | 1544 |
1541 // Restore receiver to edx as finish sequence assumes it's here. | 1545 // Restore receiver to edx as finish sequence assumes it's here. |
1542 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1546 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1543 | 1547 |
1544 // Increment element's and array's sizes. | 1548 // Increment element's and array's sizes. |
1545 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), | 1549 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), |
1546 Immediate(Smi::FromInt(kAllocationDelta))); | 1550 Immediate(Smi::FromInt(kAllocationDelta))); |
1547 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1551 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
1548 | 1552 |
(...skipping 25 matching lines...) Expand all Loading... |
1574 String* name) { | 1578 String* name) { |
1575 // ----------- S t a t e ------------- | 1579 // ----------- S t a t e ------------- |
1576 // -- ecx : name | 1580 // -- ecx : name |
1577 // -- esp[0] : return address | 1581 // -- esp[0] : return address |
1578 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1582 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1579 // -- ... | 1583 // -- ... |
1580 // -- esp[(argc + 1) * 4] : receiver | 1584 // -- esp[(argc + 1) * 4] : receiver |
1581 // ----------------------------------- | 1585 // ----------------------------------- |
1582 | 1586 |
1583 // If object is not an array, bail out to regular call. | 1587 // If object is not an array, bail out to regular call. |
1584 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); | 1588 if (!object->IsJSArray() || cell != NULL) return HEAP->undefined_value(); |
1585 | 1589 |
1586 Label miss, return_undefined, call_builtin; | 1590 Label miss, return_undefined, call_builtin; |
1587 | 1591 |
1588 GenerateNameCheck(name, &miss); | 1592 GenerateNameCheck(name, &miss); |
1589 | 1593 |
1590 // Get the receiver from the stack. | 1594 // Get the receiver from the stack. |
1591 const int argc = arguments().immediate(); | 1595 const int argc = arguments().immediate(); |
1592 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1596 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1593 | 1597 |
1594 // Check that the receiver isn't a smi. | 1598 // Check that the receiver isn't a smi. |
1595 __ test(edx, Immediate(kSmiTagMask)); | 1599 __ test(edx, Immediate(kSmiTagMask)); |
1596 __ j(zero, &miss); | 1600 __ j(zero, &miss); |
1597 CheckPrototypes(JSObject::cast(object), edx, | 1601 CheckPrototypes(JSObject::cast(object), edx, |
1598 holder, ebx, | 1602 holder, ebx, |
1599 eax, edi, name, &miss); | 1603 eax, edi, name, &miss); |
1600 | 1604 |
1601 // Get the elements array of the object. | 1605 // Get the elements array of the object. |
1602 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1606 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1603 | 1607 |
1604 // Check that the elements are in fast mode and writable. | 1608 // Check that the elements are in fast mode and writable. |
1605 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1609 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1606 Immediate(Factory::fixed_array_map())); | 1610 Immediate(FACTORY->fixed_array_map())); |
1607 __ j(not_equal, &call_builtin); | 1611 __ j(not_equal, &call_builtin); |
1608 | 1612 |
1609 // Get the array's length into ecx and calculate new length. | 1613 // Get the array's length into ecx and calculate new length. |
1610 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); | 1614 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); |
1611 __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); | 1615 __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); |
1612 __ j(negative, &return_undefined); | 1616 __ j(negative, &return_undefined); |
1613 | 1617 |
1614 // Get the last element. | 1618 // Get the last element. |
1615 STATIC_ASSERT(kSmiTagSize == 1); | 1619 STATIC_ASSERT(kSmiTagSize == 1); |
1616 STATIC_ASSERT(kSmiTag == 0); | 1620 STATIC_ASSERT(kSmiTag == 0); |
1617 __ mov(eax, FieldOperand(ebx, | 1621 __ mov(eax, FieldOperand(ebx, |
1618 ecx, times_half_pointer_size, | 1622 ecx, times_half_pointer_size, |
1619 FixedArray::kHeaderSize)); | 1623 FixedArray::kHeaderSize)); |
1620 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | 1624 __ cmp(Operand(eax), Immediate(FACTORY->the_hole_value())); |
1621 __ j(equal, &call_builtin); | 1625 __ j(equal, &call_builtin); |
1622 | 1626 |
1623 // Set the array's length. | 1627 // Set the array's length. |
1624 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); | 1628 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); |
1625 | 1629 |
1626 // Fill with the hole. | 1630 // Fill with the hole. |
1627 __ mov(FieldOperand(ebx, | 1631 __ mov(FieldOperand(ebx, |
1628 ecx, times_half_pointer_size, | 1632 ecx, times_half_pointer_size, |
1629 FixedArray::kHeaderSize), | 1633 FixedArray::kHeaderSize), |
1630 Immediate(Factory::the_hole_value())); | 1634 Immediate(FACTORY->the_hole_value())); |
1631 __ ret((argc + 1) * kPointerSize); | 1635 __ ret((argc + 1) * kPointerSize); |
1632 | 1636 |
1633 __ bind(&return_undefined); | 1637 __ bind(&return_undefined); |
1634 __ mov(eax, Immediate(Factory::undefined_value())); | 1638 __ mov(eax, Immediate(FACTORY->undefined_value())); |
1635 __ ret((argc + 1) * kPointerSize); | 1639 __ ret((argc + 1) * kPointerSize); |
1636 | 1640 |
1637 __ bind(&call_builtin); | 1641 __ bind(&call_builtin); |
1638 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), | 1642 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), |
1639 argc + 1, | 1643 argc + 1, |
1640 1); | 1644 1); |
1641 | 1645 |
1642 __ bind(&miss); | 1646 __ bind(&miss); |
1643 Object* obj; | 1647 Object* obj; |
1644 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1648 { MaybeObject* maybe_obj = GenerateMissBranch(); |
(...skipping 13 matching lines...) Expand all Loading... |
1658 String* name) { | 1662 String* name) { |
1659 // ----------- S t a t e ------------- | 1663 // ----------- S t a t e ------------- |
1660 // -- ecx : function name | 1664 // -- ecx : function name |
1661 // -- esp[0] : return address | 1665 // -- esp[0] : return address |
1662 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1666 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1663 // -- ... | 1667 // -- ... |
1664 // -- esp[(argc + 1) * 4] : receiver | 1668 // -- esp[(argc + 1) * 4] : receiver |
1665 // ----------------------------------- | 1669 // ----------------------------------- |
1666 | 1670 |
1667 // If object is not a string, bail out to regular call. | 1671 // If object is not a string, bail out to regular call. |
1668 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); | 1672 if (!object->IsString() || cell != NULL) return HEAP->undefined_value(); |
1669 | 1673 |
1670 const int argc = arguments().immediate(); | 1674 const int argc = arguments().immediate(); |
1671 | 1675 |
1672 Label miss; | 1676 Label miss; |
1673 Label name_miss; | 1677 Label name_miss; |
1674 Label index_out_of_range; | 1678 Label index_out_of_range; |
1675 Label* index_out_of_range_label = &index_out_of_range; | 1679 Label* index_out_of_range_label = &index_out_of_range; |
1676 | 1680 |
1677 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { | 1681 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { |
1678 index_out_of_range_label = &miss; | 1682 index_out_of_range_label = &miss; |
(...skipping 11 matching lines...) Expand all Loading... |
1690 ebx, edx, edi, name, &miss); | 1694 ebx, edx, edi, name, &miss); |
1691 | 1695 |
1692 Register receiver = ebx; | 1696 Register receiver = ebx; |
1693 Register index = edi; | 1697 Register index = edi; |
1694 Register scratch = edx; | 1698 Register scratch = edx; |
1695 Register result = eax; | 1699 Register result = eax; |
1696 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1700 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1697 if (argc > 0) { | 1701 if (argc > 0) { |
1698 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1702 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1699 } else { | 1703 } else { |
1700 __ Set(index, Immediate(Factory::undefined_value())); | 1704 __ Set(index, Immediate(FACTORY->undefined_value())); |
1701 } | 1705 } |
1702 | 1706 |
1703 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1707 StringCharCodeAtGenerator char_code_at_generator(receiver, |
1704 index, | 1708 index, |
1705 scratch, | 1709 scratch, |
1706 result, | 1710 result, |
1707 &miss, // When not a string. | 1711 &miss, // When not a string. |
1708 &miss, // When not a number. | 1712 &miss, // When not a number. |
1709 index_out_of_range_label, | 1713 index_out_of_range_label, |
1710 STRING_INDEX_IS_NUMBER); | 1714 STRING_INDEX_IS_NUMBER); |
1711 char_code_at_generator.GenerateFast(masm()); | 1715 char_code_at_generator.GenerateFast(masm()); |
1712 __ ret((argc + 1) * kPointerSize); | 1716 __ ret((argc + 1) * kPointerSize); |
1713 | 1717 |
1714 StubRuntimeCallHelper call_helper; | 1718 StubRuntimeCallHelper call_helper; |
1715 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1719 char_code_at_generator.GenerateSlow(masm(), call_helper); |
1716 | 1720 |
1717 if (index_out_of_range.is_linked()) { | 1721 if (index_out_of_range.is_linked()) { |
1718 __ bind(&index_out_of_range); | 1722 __ bind(&index_out_of_range); |
1719 __ Set(eax, Immediate(Factory::nan_value())); | 1723 __ Set(eax, Immediate(FACTORY->nan_value())); |
1720 __ ret((argc + 1) * kPointerSize); | 1724 __ ret((argc + 1) * kPointerSize); |
1721 } | 1725 } |
1722 | 1726 |
1723 __ bind(&miss); | 1727 __ bind(&miss); |
1724 // Restore function name in ecx. | 1728 // Restore function name in ecx. |
1725 __ Set(ecx, Immediate(Handle<String>(name))); | 1729 __ Set(ecx, Immediate(Handle<String>(name))); |
1726 __ bind(&name_miss); | 1730 __ bind(&name_miss); |
1727 Object* obj; | 1731 Object* obj; |
1728 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1732 { MaybeObject* maybe_obj = GenerateMissBranch(); |
1729 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1733 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 12 matching lines...) Expand all Loading... |
1742 String* name) { | 1746 String* name) { |
1743 // ----------- S t a t e ------------- | 1747 // ----------- S t a t e ------------- |
1744 // -- ecx : function name | 1748 // -- ecx : function name |
1745 // -- esp[0] : return address | 1749 // -- esp[0] : return address |
1746 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1750 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1747 // -- ... | 1751 // -- ... |
1748 // -- esp[(argc + 1) * 4] : receiver | 1752 // -- esp[(argc + 1) * 4] : receiver |
1749 // ----------------------------------- | 1753 // ----------------------------------- |
1750 | 1754 |
1751 // If object is not a string, bail out to regular call. | 1755 // If object is not a string, bail out to regular call. |
1752 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); | 1756 if (!object->IsString() || cell != NULL) return HEAP->undefined_value(); |
1753 | 1757 |
1754 const int argc = arguments().immediate(); | 1758 const int argc = arguments().immediate(); |
1755 | 1759 |
1756 Label miss; | 1760 Label miss; |
1757 Label name_miss; | 1761 Label name_miss; |
1758 Label index_out_of_range; | 1762 Label index_out_of_range; |
1759 Label* index_out_of_range_label = &index_out_of_range; | 1763 Label* index_out_of_range_label = &index_out_of_range; |
1760 | 1764 |
1761 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { | 1765 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { |
1762 index_out_of_range_label = &miss; | 1766 index_out_of_range_label = &miss; |
(...skipping 12 matching lines...) Expand all Loading... |
1775 | 1779 |
1776 Register receiver = eax; | 1780 Register receiver = eax; |
1777 Register index = edi; | 1781 Register index = edi; |
1778 Register scratch1 = ebx; | 1782 Register scratch1 = ebx; |
1779 Register scratch2 = edx; | 1783 Register scratch2 = edx; |
1780 Register result = eax; | 1784 Register result = eax; |
1781 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1785 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1782 if (argc > 0) { | 1786 if (argc > 0) { |
1783 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1787 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1784 } else { | 1788 } else { |
1785 __ Set(index, Immediate(Factory::undefined_value())); | 1789 __ Set(index, Immediate(FACTORY->undefined_value())); |
1786 } | 1790 } |
1787 | 1791 |
1788 StringCharAtGenerator char_at_generator(receiver, | 1792 StringCharAtGenerator char_at_generator(receiver, |
1789 index, | 1793 index, |
1790 scratch1, | 1794 scratch1, |
1791 scratch2, | 1795 scratch2, |
1792 result, | 1796 result, |
1793 &miss, // When not a string. | 1797 &miss, // When not a string. |
1794 &miss, // When not a number. | 1798 &miss, // When not a number. |
1795 index_out_of_range_label, | 1799 index_out_of_range_label, |
1796 STRING_INDEX_IS_NUMBER); | 1800 STRING_INDEX_IS_NUMBER); |
1797 char_at_generator.GenerateFast(masm()); | 1801 char_at_generator.GenerateFast(masm()); |
1798 __ ret((argc + 1) * kPointerSize); | 1802 __ ret((argc + 1) * kPointerSize); |
1799 | 1803 |
1800 StubRuntimeCallHelper call_helper; | 1804 StubRuntimeCallHelper call_helper; |
1801 char_at_generator.GenerateSlow(masm(), call_helper); | 1805 char_at_generator.GenerateSlow(masm(), call_helper); |
1802 | 1806 |
1803 if (index_out_of_range.is_linked()) { | 1807 if (index_out_of_range.is_linked()) { |
1804 __ bind(&index_out_of_range); | 1808 __ bind(&index_out_of_range); |
1805 __ Set(eax, Immediate(Factory::empty_string())); | 1809 __ Set(eax, Immediate(FACTORY->empty_string())); |
1806 __ ret((argc + 1) * kPointerSize); | 1810 __ ret((argc + 1) * kPointerSize); |
1807 } | 1811 } |
1808 | 1812 |
1809 __ bind(&miss); | 1813 __ bind(&miss); |
1810 // Restore function name in ecx. | 1814 // Restore function name in ecx. |
1811 __ Set(ecx, Immediate(Handle<String>(name))); | 1815 __ Set(ecx, Immediate(Handle<String>(name))); |
1812 __ bind(&name_miss); | 1816 __ bind(&name_miss); |
1813 Object* obj; | 1817 Object* obj; |
1814 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1818 { MaybeObject* maybe_obj = GenerateMissBranch(); |
1815 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1819 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 15 matching lines...) Expand all Loading... |
1831 // -- esp[0] : return address | 1835 // -- esp[0] : return address |
1832 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1836 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1833 // -- ... | 1837 // -- ... |
1834 // -- esp[(argc + 1) * 4] : receiver | 1838 // -- esp[(argc + 1) * 4] : receiver |
1835 // ----------------------------------- | 1839 // ----------------------------------- |
1836 | 1840 |
1837 const int argc = arguments().immediate(); | 1841 const int argc = arguments().immediate(); |
1838 | 1842 |
1839 // If the object is not a JSObject or we got an unexpected number of | 1843 // If the object is not a JSObject or we got an unexpected number of |
1840 // arguments, bail out to the regular call. | 1844 // arguments, bail out to the regular call. |
1841 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | 1845 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); |
1842 | 1846 |
1843 Label miss; | 1847 Label miss; |
1844 GenerateNameCheck(name, &miss); | 1848 GenerateNameCheck(name, &miss); |
1845 | 1849 |
1846 if (cell == NULL) { | 1850 if (cell == NULL) { |
1847 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1851 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1848 | 1852 |
1849 STATIC_ASSERT(kSmiTag == 0); | 1853 STATIC_ASSERT(kSmiTag == 0); |
1850 __ test(edx, Immediate(kSmiTagMask)); | 1854 __ test(edx, Immediate(kSmiTagMask)); |
1851 __ j(zero, &miss); | 1855 __ j(zero, &miss); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 JSFunction* function, | 1905 JSFunction* function, |
1902 String* name) { | 1906 String* name) { |
1903 // ----------- S t a t e ------------- | 1907 // ----------- S t a t e ------------- |
1904 // -- ecx : name | 1908 // -- ecx : name |
1905 // -- esp[0] : return address | 1909 // -- esp[0] : return address |
1906 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1910 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1907 // -- ... | 1911 // -- ... |
1908 // -- esp[(argc + 1) * 4] : receiver | 1912 // -- esp[(argc + 1) * 4] : receiver |
1909 // ----------------------------------- | 1913 // ----------------------------------- |
1910 | 1914 |
1911 if (!CpuFeatures::IsSupported(SSE2)) return Heap::undefined_value(); | 1915 if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) |
| 1916 return HEAP->undefined_value(); |
1912 CpuFeatures::Scope use_sse2(SSE2); | 1917 CpuFeatures::Scope use_sse2(SSE2); |
1913 | 1918 |
1914 const int argc = arguments().immediate(); | 1919 const int argc = arguments().immediate(); |
1915 | 1920 |
1916 // If the object is not a JSObject or we got an unexpected number of | 1921 // If the object is not a JSObject or we got an unexpected number of |
1917 // arguments, bail out to the regular call. | 1922 // arguments, bail out to the regular call. |
1918 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | 1923 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); |
1919 | 1924 |
1920 Label miss; | 1925 Label miss; |
1921 GenerateNameCheck(name, &miss); | 1926 GenerateNameCheck(name, &miss); |
1922 | 1927 |
1923 if (cell == NULL) { | 1928 if (cell == NULL) { |
1924 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1929 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1925 | 1930 |
1926 STATIC_ASSERT(kSmiTag == 0); | 1931 STATIC_ASSERT(kSmiTag == 0); |
1927 __ test(edx, Immediate(kSmiTagMask)); | 1932 __ test(edx, Immediate(kSmiTagMask)); |
1928 __ j(zero, &miss); | 1933 __ j(zero, &miss); |
(...skipping 10 matching lines...) Expand all Loading... |
1939 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 1944 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
1940 | 1945 |
1941 // Check if the argument is a smi. | 1946 // Check if the argument is a smi. |
1942 Label smi; | 1947 Label smi; |
1943 STATIC_ASSERT(kSmiTag == 0); | 1948 STATIC_ASSERT(kSmiTag == 0); |
1944 __ test(eax, Immediate(kSmiTagMask)); | 1949 __ test(eax, Immediate(kSmiTagMask)); |
1945 __ j(zero, &smi); | 1950 __ j(zero, &smi); |
1946 | 1951 |
1947 // Check if the argument is a heap number and load its value into xmm0. | 1952 // Check if the argument is a heap number and load its value into xmm0. |
1948 Label slow; | 1953 Label slow; |
1949 __ CheckMap(eax, Factory::heap_number_map(), &slow, true); | 1954 __ CheckMap(eax, FACTORY->heap_number_map(), &slow, true); |
1950 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 1955 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
1951 | 1956 |
1952 // Check if the argument is strictly positive. Note this also | 1957 // Check if the argument is strictly positive. Note this also |
1953 // discards NaN. | 1958 // discards NaN. |
1954 __ xorpd(xmm1, xmm1); | 1959 __ xorpd(xmm1, xmm1); |
1955 __ ucomisd(xmm0, xmm1); | 1960 __ ucomisd(xmm0, xmm1); |
1956 __ j(below_equal, &slow); | 1961 __ j(below_equal, &slow); |
1957 | 1962 |
1958 // Do a truncating conversion. | 1963 // Do a truncating conversion. |
1959 __ cvttsd2si(eax, Operand(xmm0)); | 1964 __ cvttsd2si(eax, Operand(xmm0)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 // -- esp[0] : return address | 2037 // -- esp[0] : return address |
2033 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2038 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2034 // -- ... | 2039 // -- ... |
2035 // -- esp[(argc + 1) * 4] : receiver | 2040 // -- esp[(argc + 1) * 4] : receiver |
2036 // ----------------------------------- | 2041 // ----------------------------------- |
2037 | 2042 |
2038 const int argc = arguments().immediate(); | 2043 const int argc = arguments().immediate(); |
2039 | 2044 |
2040 // If the object is not a JSObject or we got an unexpected number of | 2045 // If the object is not a JSObject or we got an unexpected number of |
2041 // arguments, bail out to the regular call. | 2046 // arguments, bail out to the regular call. |
2042 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | 2047 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); |
2043 | 2048 |
2044 Label miss; | 2049 Label miss; |
2045 GenerateNameCheck(name, &miss); | 2050 GenerateNameCheck(name, &miss); |
2046 | 2051 |
2047 if (cell == NULL) { | 2052 if (cell == NULL) { |
2048 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2053 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2049 | 2054 |
2050 STATIC_ASSERT(kSmiTag == 0); | 2055 STATIC_ASSERT(kSmiTag == 0); |
2051 __ test(edx, Immediate(kSmiTagMask)); | 2056 __ test(edx, Immediate(kSmiTagMask)); |
2052 __ j(zero, &miss); | 2057 __ j(zero, &miss); |
(...skipping 30 matching lines...) Expand all Loading... |
2083 // This only happens for the most negative smi. | 2088 // This only happens for the most negative smi. |
2084 Label slow; | 2089 Label slow; |
2085 __ j(negative, &slow); | 2090 __ j(negative, &slow); |
2086 | 2091 |
2087 // Smi case done. | 2092 // Smi case done. |
2088 __ ret(2 * kPointerSize); | 2093 __ ret(2 * kPointerSize); |
2089 | 2094 |
2090 // Check if the argument is a heap number and load its exponent and | 2095 // Check if the argument is a heap number and load its exponent and |
2091 // sign into ebx. | 2096 // sign into ebx. |
2092 __ bind(¬_smi); | 2097 __ bind(¬_smi); |
2093 __ CheckMap(eax, Factory::heap_number_map(), &slow, true); | 2098 __ CheckMap(eax, FACTORY->heap_number_map(), &slow, true); |
2094 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 2099 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
2095 | 2100 |
2096 // Check the sign of the argument. If the argument is positive, | 2101 // Check the sign of the argument. If the argument is positive, |
2097 // just return it. | 2102 // just return it. |
2098 Label negative_sign; | 2103 Label negative_sign; |
2099 __ test(ebx, Immediate(HeapNumber::kSignMask)); | 2104 __ test(ebx, Immediate(HeapNumber::kSignMask)); |
2100 __ j(not_zero, &negative_sign); | 2105 __ j(not_zero, &negative_sign); |
2101 __ ret(2 * kPointerSize); | 2106 __ ret(2 * kPointerSize); |
2102 | 2107 |
2103 // If the argument is negative, clear the sign, and return a new | 2108 // If the argument is negative, clear the sign, and return a new |
(...skipping 26 matching lines...) Expand all Loading... |
2130 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2135 MaybeObject* CallStubCompiler::CompileFastApiCall( |
2131 const CallOptimization& optimization, | 2136 const CallOptimization& optimization, |
2132 Object* object, | 2137 Object* object, |
2133 JSObject* holder, | 2138 JSObject* holder, |
2134 JSGlobalPropertyCell* cell, | 2139 JSGlobalPropertyCell* cell, |
2135 JSFunction* function, | 2140 JSFunction* function, |
2136 String* name) { | 2141 String* name) { |
2137 ASSERT(optimization.is_simple_api_call()); | 2142 ASSERT(optimization.is_simple_api_call()); |
2138 // Bail out if object is a global object as we don't want to | 2143 // Bail out if object is a global object as we don't want to |
2139 // repatch it to global receiver. | 2144 // repatch it to global receiver. |
2140 if (object->IsGlobalObject()) return Heap::undefined_value(); | 2145 if (object->IsGlobalObject()) return HEAP->undefined_value(); |
2141 if (cell != NULL) return Heap::undefined_value(); | 2146 if (cell != NULL) return HEAP->undefined_value(); |
2142 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2147 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2143 JSObject::cast(object), holder); | 2148 JSObject::cast(object), holder); |
2144 if (depth == kInvalidProtoDepth) return Heap::undefined_value(); | 2149 if (depth == kInvalidProtoDepth) return HEAP->undefined_value(); |
2145 | 2150 |
2146 Label miss, miss_before_stack_reserved; | 2151 Label miss, miss_before_stack_reserved; |
2147 | 2152 |
2148 GenerateNameCheck(name, &miss_before_stack_reserved); | 2153 GenerateNameCheck(name, &miss_before_stack_reserved); |
2149 | 2154 |
2150 // Get the receiver from the stack. | 2155 // Get the receiver from the stack. |
2151 const int argc = arguments().immediate(); | 2156 const int argc = arguments().immediate(); |
2152 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2157 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2153 | 2158 |
2154 // Check that the receiver isn't a smi. | 2159 // Check that the receiver isn't a smi. |
2155 __ test(edx, Immediate(kSmiTagMask)); | 2160 __ test(edx, Immediate(kSmiTagMask)); |
2156 __ j(zero, &miss_before_stack_reserved, not_taken); | 2161 __ j(zero, &miss_before_stack_reserved, not_taken); |
2157 | 2162 |
2158 __ IncrementCounter(&Counters::call_const, 1); | 2163 __ IncrementCounter(COUNTERS->call_const(), 1); |
2159 __ IncrementCounter(&Counters::call_const_fast_api, 1); | 2164 __ IncrementCounter(COUNTERS->call_const_fast_api(), 1); |
2160 | 2165 |
2161 // Allocate space for v8::Arguments implicit values. Must be initialized | 2166 // Allocate space for v8::Arguments implicit values. Must be initialized |
2162 // before calling any runtime function. | 2167 // before calling any runtime function. |
2163 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2168 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2164 | 2169 |
2165 // Check that the maps haven't changed and find a Holder as a side effect. | 2170 // Check that the maps haven't changed and find a Holder as a side effect. |
2166 CheckPrototypes(JSObject::cast(object), edx, holder, | 2171 CheckPrototypes(JSObject::cast(object), edx, holder, |
2167 ebx, eax, edi, name, depth, &miss); | 2172 ebx, eax, edi, name, depth, &miss); |
2168 | 2173 |
2169 // Move the return address on top of the stack. | 2174 // Move the return address on top of the stack. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 __ j(zero, &miss, not_taken); | 2230 __ j(zero, &miss, not_taken); |
2226 } | 2231 } |
2227 | 2232 |
2228 // Make sure that it's okay not to patch the on stack receiver | 2233 // Make sure that it's okay not to patch the on stack receiver |
2229 // unless we're doing a receiver map check. | 2234 // unless we're doing a receiver map check. |
2230 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2235 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2231 | 2236 |
2232 SharedFunctionInfo* function_info = function->shared(); | 2237 SharedFunctionInfo* function_info = function->shared(); |
2233 switch (check) { | 2238 switch (check) { |
2234 case RECEIVER_MAP_CHECK: | 2239 case RECEIVER_MAP_CHECK: |
2235 __ IncrementCounter(&Counters::call_const, 1); | 2240 __ IncrementCounter(COUNTERS->call_const(), 1); |
2236 | 2241 |
2237 // Check that the maps haven't changed. | 2242 // Check that the maps haven't changed. |
2238 CheckPrototypes(JSObject::cast(object), edx, holder, | 2243 CheckPrototypes(JSObject::cast(object), edx, holder, |
2239 ebx, eax, edi, name, &miss); | 2244 ebx, eax, edi, name, &miss); |
2240 | 2245 |
2241 // Patch the receiver on the stack with the global proxy if | 2246 // Patch the receiver on the stack with the global proxy if |
2242 // necessary. | 2247 // necessary. |
2243 if (object->IsGlobalObject()) { | 2248 if (object->IsGlobalObject()) { |
2244 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2249 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2245 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2250 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2286 } | 2291 } |
2287 | 2292 |
2288 case BOOLEAN_CHECK: { | 2293 case BOOLEAN_CHECK: { |
2289 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2294 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2290 // Calling non-strict non-builtins with a value as the receiver | 2295 // Calling non-strict non-builtins with a value as the receiver |
2291 // requires boxing. | 2296 // requires boxing. |
2292 __ jmp(&miss); | 2297 __ jmp(&miss); |
2293 } else { | 2298 } else { |
2294 Label fast; | 2299 Label fast; |
2295 // Check that the object is a boolean. | 2300 // Check that the object is a boolean. |
2296 __ cmp(edx, Factory::true_value()); | 2301 __ cmp(edx, FACTORY->true_value()); |
2297 __ j(equal, &fast, taken); | 2302 __ j(equal, &fast, taken); |
2298 __ cmp(edx, Factory::false_value()); | 2303 __ cmp(edx, FACTORY->false_value()); |
2299 __ j(not_equal, &miss, not_taken); | 2304 __ j(not_equal, &miss, not_taken); |
2300 __ bind(&fast); | 2305 __ bind(&fast); |
2301 // Check that the maps starting from the prototype haven't changed. | 2306 // Check that the maps starting from the prototype haven't changed. |
2302 GenerateDirectLoadGlobalFunctionPrototype( | 2307 GenerateDirectLoadGlobalFunctionPrototype( |
2303 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2308 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
2304 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2309 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2305 ebx, edx, edi, name, &miss); | 2310 ebx, edx, edi, name, &miss); |
2306 } | 2311 } |
2307 break; | 2312 break; |
2308 } | 2313 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2429 // Patch the receiver on the stack with the global proxy. | 2434 // Patch the receiver on the stack with the global proxy. |
2430 if (object->IsGlobalObject()) { | 2435 if (object->IsGlobalObject()) { |
2431 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2436 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2432 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2437 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2433 } | 2438 } |
2434 | 2439 |
2435 // Setup the context (function already in edi). | 2440 // Setup the context (function already in edi). |
2436 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2441 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2437 | 2442 |
2438 // Jump to the cached code (tail call). | 2443 // Jump to the cached code (tail call). |
2439 __ IncrementCounter(&Counters::call_global_inline, 1); | 2444 __ IncrementCounter(COUNTERS->call_global_inline(), 1); |
2440 ASSERT(function->is_compiled()); | 2445 ASSERT(function->is_compiled()); |
2441 ParameterCount expected(function->shared()->formal_parameter_count()); | 2446 ParameterCount expected(function->shared()->formal_parameter_count()); |
2442 if (V8::UseCrankshaft()) { | 2447 if (V8::UseCrankshaft()) { |
2443 // TODO(kasperl): For now, we always call indirectly through the | 2448 // TODO(kasperl): For now, we always call indirectly through the |
2444 // code field in the function to allow recompilation to take effect | 2449 // code field in the function to allow recompilation to take effect |
2445 // without changing any of the call sites. | 2450 // without changing any of the call sites. |
2446 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2451 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2447 expected, arguments(), JUMP_FUNCTION); | 2452 expected, arguments(), JUMP_FUNCTION); |
2448 } else { | 2453 } else { |
2449 Handle<Code> code(function->code()); | 2454 Handle<Code> code(function->code()); |
2450 __ InvokeCode(code, expected, arguments(), | 2455 __ InvokeCode(code, expected, arguments(), |
2451 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 2456 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
2452 } | 2457 } |
2453 | 2458 |
2454 // Handle call cache miss. | 2459 // Handle call cache miss. |
2455 __ bind(&miss); | 2460 __ bind(&miss); |
2456 __ IncrementCounter(&Counters::call_global_inline_miss, 1); | 2461 __ IncrementCounter(COUNTERS->call_global_inline_miss(), 1); |
2457 Object* obj; | 2462 Object* obj; |
2458 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2463 { MaybeObject* maybe_obj = GenerateMissBranch(); |
2459 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2464 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2460 } | 2465 } |
2461 | 2466 |
2462 // Return the generated code. | 2467 // Return the generated code. |
2463 return GetCode(NORMAL, name); | 2468 return GetCode(NORMAL, name); |
2464 } | 2469 } |
2465 | 2470 |
2466 | 2471 |
(...skipping 13 matching lines...) Expand all Loading... |
2480 GenerateStoreField(masm(), | 2485 GenerateStoreField(masm(), |
2481 object, | 2486 object, |
2482 index, | 2487 index, |
2483 transition, | 2488 transition, |
2484 edx, ecx, ebx, | 2489 edx, ecx, ebx, |
2485 &miss); | 2490 &miss); |
2486 | 2491 |
2487 // Handle store cache miss. | 2492 // Handle store cache miss. |
2488 __ bind(&miss); | 2493 __ bind(&miss); |
2489 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2494 __ mov(ecx, Immediate(Handle<String>(name))); // restore name |
2490 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 2495 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2496 Builtins::StoreIC_Miss)); |
2491 __ jmp(ic, RelocInfo::CODE_TARGET); | 2497 __ jmp(ic, RelocInfo::CODE_TARGET); |
2492 | 2498 |
2493 // Return the generated code. | 2499 // Return the generated code. |
2494 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2500 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2495 } | 2501 } |
2496 | 2502 |
2497 | 2503 |
2498 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2504 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, |
2499 AccessorInfo* callback, | 2505 AccessorInfo* callback, |
2500 String* name) { | 2506 String* name) { |
(...skipping 30 matching lines...) Expand all Loading... |
2531 __ push(eax); // value | 2537 __ push(eax); // value |
2532 __ push(ebx); // restore return address | 2538 __ push(ebx); // restore return address |
2533 | 2539 |
2534 // Do tail-call to the runtime system. | 2540 // Do tail-call to the runtime system. |
2535 ExternalReference store_callback_property = | 2541 ExternalReference store_callback_property = |
2536 ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); | 2542 ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); |
2537 __ TailCallExternalReference(store_callback_property, 4, 1); | 2543 __ TailCallExternalReference(store_callback_property, 4, 1); |
2538 | 2544 |
2539 // Handle store cache miss. | 2545 // Handle store cache miss. |
2540 __ bind(&miss); | 2546 __ bind(&miss); |
2541 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 2547 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2548 Builtins::StoreIC_Miss)); |
2542 __ jmp(ic, RelocInfo::CODE_TARGET); | 2549 __ jmp(ic, RelocInfo::CODE_TARGET); |
2543 | 2550 |
2544 // Return the generated code. | 2551 // Return the generated code. |
2545 return GetCode(CALLBACKS, name); | 2552 return GetCode(CALLBACKS, name); |
2546 } | 2553 } |
2547 | 2554 |
2548 | 2555 |
2549 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2556 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, |
2550 String* name) { | 2557 String* name) { |
2551 // ----------- S t a t e ------------- | 2558 // ----------- S t a t e ------------- |
(...skipping 29 matching lines...) Expand all Loading... |
2581 __ push(Immediate(Smi::FromInt(strict_mode_))); | 2588 __ push(Immediate(Smi::FromInt(strict_mode_))); |
2582 __ push(ebx); // restore return address | 2589 __ push(ebx); // restore return address |
2583 | 2590 |
2584 // Do tail-call to the runtime system. | 2591 // Do tail-call to the runtime system. |
2585 ExternalReference store_ic_property = | 2592 ExternalReference store_ic_property = |
2586 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); | 2593 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); |
2587 __ TailCallExternalReference(store_ic_property, 4, 1); | 2594 __ TailCallExternalReference(store_ic_property, 4, 1); |
2588 | 2595 |
2589 // Handle store cache miss. | 2596 // Handle store cache miss. |
2590 __ bind(&miss); | 2597 __ bind(&miss); |
2591 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 2598 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2599 Builtins::StoreIC_Miss)); |
2592 __ jmp(ic, RelocInfo::CODE_TARGET); | 2600 __ jmp(ic, RelocInfo::CODE_TARGET); |
2593 | 2601 |
2594 // Return the generated code. | 2602 // Return the generated code. |
2595 return GetCode(INTERCEPTOR, name); | 2603 return GetCode(INTERCEPTOR, name); |
2596 } | 2604 } |
2597 | 2605 |
2598 | 2606 |
2599 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2607 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, |
2600 JSGlobalPropertyCell* cell, | 2608 JSGlobalPropertyCell* cell, |
2601 String* name) { | 2609 String* name) { |
(...skipping 15 matching lines...) Expand all Loading... |
2617 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2625 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); |
2618 if (Serializer::enabled()) { | 2626 if (Serializer::enabled()) { |
2619 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2627 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2620 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2628 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2621 } | 2629 } |
2622 | 2630 |
2623 // Check that the value in the cell is not the hole. If it is, this | 2631 // Check that the value in the cell is not the hole. If it is, this |
2624 // cell could have been deleted and reintroducing the global needs | 2632 // cell could have been deleted and reintroducing the global needs |
2625 // to update the property details in the property dictionary of the | 2633 // to update the property details in the property dictionary of the |
2626 // global object. We bail out to the runtime system to do that. | 2634 // global object. We bail out to the runtime system to do that. |
2627 __ cmp(cell_operand, Factory::the_hole_value()); | 2635 __ cmp(cell_operand, FACTORY->the_hole_value()); |
2628 __ j(equal, &miss); | 2636 __ j(equal, &miss); |
2629 | 2637 |
2630 // Store the value in the cell. | 2638 // Store the value in the cell. |
2631 __ mov(cell_operand, eax); | 2639 __ mov(cell_operand, eax); |
2632 | 2640 |
2633 // Return the value (register eax). | 2641 // Return the value (register eax). |
2634 __ IncrementCounter(&Counters::named_store_global_inline, 1); | 2642 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1); |
2635 __ ret(0); | 2643 __ ret(0); |
2636 | 2644 |
2637 // Handle store cache miss. | 2645 // Handle store cache miss. |
2638 __ bind(&miss); | 2646 __ bind(&miss); |
2639 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1); | 2647 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1); |
2640 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 2648 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2649 Builtins::StoreIC_Miss)); |
2641 __ jmp(ic, RelocInfo::CODE_TARGET); | 2650 __ jmp(ic, RelocInfo::CODE_TARGET); |
2642 | 2651 |
2643 // Return the generated code. | 2652 // Return the generated code. |
2644 return GetCode(NORMAL, name); | 2653 return GetCode(NORMAL, name); |
2645 } | 2654 } |
2646 | 2655 |
2647 | 2656 |
2648 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2657 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
2649 int index, | 2658 int index, |
2650 Map* transition, | 2659 Map* transition, |
2651 String* name) { | 2660 String* name) { |
2652 // ----------- S t a t e ------------- | 2661 // ----------- S t a t e ------------- |
2653 // -- eax : value | 2662 // -- eax : value |
2654 // -- ecx : key | 2663 // -- ecx : key |
2655 // -- edx : receiver | 2664 // -- edx : receiver |
2656 // -- esp[0] : return address | 2665 // -- esp[0] : return address |
2657 // ----------------------------------- | 2666 // ----------------------------------- |
2658 Label miss; | 2667 Label miss; |
2659 | 2668 |
2660 __ IncrementCounter(&Counters::keyed_store_field, 1); | 2669 __ IncrementCounter(COUNTERS->keyed_store_field(), 1); |
2661 | 2670 |
2662 // Check that the name has not changed. | 2671 // Check that the name has not changed. |
2663 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2672 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
2664 __ j(not_equal, &miss, not_taken); | 2673 __ j(not_equal, &miss, not_taken); |
2665 | 2674 |
2666 // Generate store field code. Trashes the name register. | 2675 // Generate store field code. Trashes the name register. |
2667 GenerateStoreField(masm(), | 2676 GenerateStoreField(masm(), |
2668 object, | 2677 object, |
2669 index, | 2678 index, |
2670 transition, | 2679 transition, |
2671 edx, ecx, ebx, | 2680 edx, ecx, ebx, |
2672 &miss); | 2681 &miss); |
2673 | 2682 |
2674 // Handle store cache miss. | 2683 // Handle store cache miss. |
2675 __ bind(&miss); | 2684 __ bind(&miss); |
2676 __ DecrementCounter(&Counters::keyed_store_field, 1); | 2685 __ DecrementCounter(COUNTERS->keyed_store_field(), 1); |
2677 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 2686 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2687 Builtins::KeyedStoreIC_Miss)); |
2678 __ jmp(ic, RelocInfo::CODE_TARGET); | 2688 __ jmp(ic, RelocInfo::CODE_TARGET); |
2679 | 2689 |
2680 // Return the generated code. | 2690 // Return the generated code. |
2681 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2691 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2682 } | 2692 } |
2683 | 2693 |
2684 | 2694 |
2685 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2695 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
2686 JSObject* receiver) { | 2696 JSObject* receiver) { |
2687 // ----------- S t a t e ------------- | 2697 // ----------- S t a t e ------------- |
(...skipping 13 matching lines...) Expand all Loading... |
2701 Immediate(Handle<Map>(receiver->map()))); | 2711 Immediate(Handle<Map>(receiver->map()))); |
2702 __ j(not_equal, &miss, not_taken); | 2712 __ j(not_equal, &miss, not_taken); |
2703 | 2713 |
2704 // Check that the key is a smi. | 2714 // Check that the key is a smi. |
2705 __ test(ecx, Immediate(kSmiTagMask)); | 2715 __ test(ecx, Immediate(kSmiTagMask)); |
2706 __ j(not_zero, &miss, not_taken); | 2716 __ j(not_zero, &miss, not_taken); |
2707 | 2717 |
2708 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2718 // Get the elements array and make sure it is a fast element array, not 'cow'. |
2709 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 2719 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
2710 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 2720 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
2711 Immediate(Factory::fixed_array_map())); | 2721 Immediate(FACTORY->fixed_array_map())); |
2712 __ j(not_equal, &miss, not_taken); | 2722 __ j(not_equal, &miss, not_taken); |
2713 | 2723 |
2714 // Check that the key is within bounds. | 2724 // Check that the key is within bounds. |
2715 if (receiver->IsJSArray()) { | 2725 if (receiver->IsJSArray()) { |
2716 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 2726 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
2717 __ j(above_equal, &miss, not_taken); | 2727 __ j(above_equal, &miss, not_taken); |
2718 } else { | 2728 } else { |
2719 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. | 2729 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
2720 __ j(above_equal, &miss, not_taken); | 2730 __ j(above_equal, &miss, not_taken); |
2721 } | 2731 } |
2722 | 2732 |
2723 // Do the store and update the write barrier. Make sure to preserve | 2733 // Do the store and update the write barrier. Make sure to preserve |
2724 // the value in register eax. | 2734 // the value in register eax. |
2725 __ mov(edx, Operand(eax)); | 2735 __ mov(edx, Operand(eax)); |
2726 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2736 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
2727 __ RecordWrite(edi, 0, edx, ecx); | 2737 __ RecordWrite(edi, 0, edx, ecx); |
2728 | 2738 |
2729 // Done. | 2739 // Done. |
2730 __ ret(0); | 2740 __ ret(0); |
2731 | 2741 |
2732 // Handle store cache miss. | 2742 // Handle store cache miss. |
2733 __ bind(&miss); | 2743 __ bind(&miss); |
2734 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 2744 Handle<Code> ic( |
| 2745 Isolate::Current()->builtins()->builtin(Builtins::KeyedStoreIC_Miss)); |
2735 __ jmp(ic, RelocInfo::CODE_TARGET); | 2746 __ jmp(ic, RelocInfo::CODE_TARGET); |
2736 | 2747 |
2737 // Return the generated code. | 2748 // Return the generated code. |
2738 return GetCode(NORMAL, NULL); | 2749 return GetCode(NORMAL, NULL); |
2739 } | 2750 } |
2740 | 2751 |
2741 | 2752 |
2742 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2753 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
2743 JSObject* object, | 2754 JSObject* object, |
2744 JSObject* last) { | 2755 JSObject* last) { |
(...skipping 24 matching lines...) Expand all Loading... |
2769 edx, | 2780 edx, |
2770 &miss); | 2781 &miss); |
2771 if (cell->IsFailure()) { | 2782 if (cell->IsFailure()) { |
2772 miss.Unuse(); | 2783 miss.Unuse(); |
2773 return cell; | 2784 return cell; |
2774 } | 2785 } |
2775 } | 2786 } |
2776 | 2787 |
2777 // Return undefined if maps of the full prototype chain are still the | 2788 // Return undefined if maps of the full prototype chain are still the |
2778 // same and no global property with this name contains a value. | 2789 // same and no global property with this name contains a value. |
2779 __ mov(eax, Factory::undefined_value()); | 2790 __ mov(eax, FACTORY->undefined_value()); |
2780 __ ret(0); | 2791 __ ret(0); |
2781 | 2792 |
2782 __ bind(&miss); | 2793 __ bind(&miss); |
2783 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2794 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2784 | 2795 |
2785 // Return the generated code. | 2796 // Return the generated code. |
2786 return GetCode(NONEXISTENT, Heap::empty_string()); | 2797 return GetCode(NONEXISTENT, HEAP->empty_string()); |
2787 } | 2798 } |
2788 | 2799 |
2789 | 2800 |
2790 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 2801 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, |
2791 JSObject* holder, | 2802 JSObject* holder, |
2792 int index, | 2803 int index, |
2793 String* name) { | 2804 String* name) { |
2794 // ----------- S t a t e ------------- | 2805 // ----------- S t a t e ------------- |
2795 // -- eax : receiver | 2806 // -- eax : receiver |
2796 // -- ecx : name | 2807 // -- ecx : name |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2913 // Get the value from the cell. | 2924 // Get the value from the cell. |
2914 if (Serializer::enabled()) { | 2925 if (Serializer::enabled()) { |
2915 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2926 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2916 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2927 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2917 } else { | 2928 } else { |
2918 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 2929 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
2919 } | 2930 } |
2920 | 2931 |
2921 // Check for deleted property if property can actually be deleted. | 2932 // Check for deleted property if property can actually be deleted. |
2922 if (!is_dont_delete) { | 2933 if (!is_dont_delete) { |
2923 __ cmp(ebx, Factory::the_hole_value()); | 2934 __ cmp(ebx, FACTORY->the_hole_value()); |
2924 __ j(equal, &miss, not_taken); | 2935 __ j(equal, &miss, not_taken); |
2925 } else if (FLAG_debug_code) { | 2936 } else if (FLAG_debug_code) { |
2926 __ cmp(ebx, Factory::the_hole_value()); | 2937 __ cmp(ebx, FACTORY->the_hole_value()); |
2927 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2938 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
2928 } | 2939 } |
2929 | 2940 |
2930 __ IncrementCounter(&Counters::named_load_global_stub, 1); | 2941 __ IncrementCounter(COUNTERS->named_load_global_stub(), 1); |
2931 __ mov(eax, ebx); | 2942 __ mov(eax, ebx); |
2932 __ ret(0); | 2943 __ ret(0); |
2933 | 2944 |
2934 __ bind(&miss); | 2945 __ bind(&miss); |
2935 __ IncrementCounter(&Counters::named_load_global_stub_miss, 1); | 2946 __ IncrementCounter(COUNTERS->named_load_global_stub_miss(), 1); |
2936 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2947 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2937 | 2948 |
2938 // Return the generated code. | 2949 // Return the generated code. |
2939 return GetCode(NORMAL, name); | 2950 return GetCode(NORMAL, name); |
2940 } | 2951 } |
2941 | 2952 |
2942 | 2953 |
2943 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 2954 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, |
2944 JSObject* receiver, | 2955 JSObject* receiver, |
2945 JSObject* holder, | 2956 JSObject* holder, |
2946 int index) { | 2957 int index) { |
2947 // ----------- S t a t e ------------- | 2958 // ----------- S t a t e ------------- |
2948 // -- eax : key | 2959 // -- eax : key |
2949 // -- edx : receiver | 2960 // -- edx : receiver |
2950 // -- esp[0] : return address | 2961 // -- esp[0] : return address |
2951 // ----------------------------------- | 2962 // ----------------------------------- |
2952 Label miss; | 2963 Label miss; |
2953 | 2964 |
2954 __ IncrementCounter(&Counters::keyed_load_field, 1); | 2965 __ IncrementCounter(COUNTERS->keyed_load_field(), 1); |
2955 | 2966 |
2956 // Check that the name has not changed. | 2967 // Check that the name has not changed. |
2957 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2968 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2958 __ j(not_equal, &miss, not_taken); | 2969 __ j(not_equal, &miss, not_taken); |
2959 | 2970 |
2960 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2971 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
2961 | 2972 |
2962 __ bind(&miss); | 2973 __ bind(&miss); |
2963 __ DecrementCounter(&Counters::keyed_load_field, 1); | 2974 __ DecrementCounter(COUNTERS->keyed_load_field(), 1); |
2964 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2975 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2965 | 2976 |
2966 // Return the generated code. | 2977 // Return the generated code. |
2967 return GetCode(FIELD, name); | 2978 return GetCode(FIELD, name); |
2968 } | 2979 } |
2969 | 2980 |
2970 | 2981 |
2971 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2982 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
2972 String* name, | 2983 String* name, |
2973 JSObject* receiver, | 2984 JSObject* receiver, |
2974 JSObject* holder, | 2985 JSObject* holder, |
2975 AccessorInfo* callback) { | 2986 AccessorInfo* callback) { |
2976 // ----------- S t a t e ------------- | 2987 // ----------- S t a t e ------------- |
2977 // -- eax : key | 2988 // -- eax : key |
2978 // -- edx : receiver | 2989 // -- edx : receiver |
2979 // -- esp[0] : return address | 2990 // -- esp[0] : return address |
2980 // ----------------------------------- | 2991 // ----------------------------------- |
2981 Label miss; | 2992 Label miss; |
2982 | 2993 |
2983 __ IncrementCounter(&Counters::keyed_load_callback, 1); | 2994 __ IncrementCounter(COUNTERS->keyed_load_callback(), 1); |
2984 | 2995 |
2985 // Check that the name has not changed. | 2996 // Check that the name has not changed. |
2986 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2997 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2987 __ j(not_equal, &miss, not_taken); | 2998 __ j(not_equal, &miss, not_taken); |
2988 | 2999 |
2989 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 3000 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
2990 ecx, edi, callback, name, &miss); | 3001 ecx, edi, callback, name, &miss); |
2991 if (result->IsFailure()) { | 3002 if (result->IsFailure()) { |
2992 miss.Unuse(); | 3003 miss.Unuse(); |
2993 return result; | 3004 return result; |
2994 } | 3005 } |
2995 | 3006 |
2996 __ bind(&miss); | 3007 __ bind(&miss); |
2997 | 3008 |
2998 __ DecrementCounter(&Counters::keyed_load_callback, 1); | 3009 __ DecrementCounter(COUNTERS->keyed_load_callback(), 1); |
2999 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3010 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3000 | 3011 |
3001 // Return the generated code. | 3012 // Return the generated code. |
3002 return GetCode(CALLBACKS, name); | 3013 return GetCode(CALLBACKS, name); |
3003 } | 3014 } |
3004 | 3015 |
3005 | 3016 |
3006 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3017 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
3007 JSObject* receiver, | 3018 JSObject* receiver, |
3008 JSObject* holder, | 3019 JSObject* holder, |
3009 Object* value) { | 3020 Object* value) { |
3010 // ----------- S t a t e ------------- | 3021 // ----------- S t a t e ------------- |
3011 // -- eax : key | 3022 // -- eax : key |
3012 // -- edx : receiver | 3023 // -- edx : receiver |
3013 // -- esp[0] : return address | 3024 // -- esp[0] : return address |
3014 // ----------------------------------- | 3025 // ----------------------------------- |
3015 Label miss; | 3026 Label miss; |
3016 | 3027 |
3017 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); | 3028 __ IncrementCounter(COUNTERS->keyed_load_constant_function(), 1); |
3018 | 3029 |
3019 // Check that the name has not changed. | 3030 // Check that the name has not changed. |
3020 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3031 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3021 __ j(not_equal, &miss, not_taken); | 3032 __ j(not_equal, &miss, not_taken); |
3022 | 3033 |
3023 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3034 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
3024 value, name, &miss); | 3035 value, name, &miss); |
3025 __ bind(&miss); | 3036 __ bind(&miss); |
3026 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); | 3037 __ DecrementCounter(COUNTERS->keyed_load_constant_function(), 1); |
3027 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3038 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3028 | 3039 |
3029 // Return the generated code. | 3040 // Return the generated code. |
3030 return GetCode(CONSTANT_FUNCTION, name); | 3041 return GetCode(CONSTANT_FUNCTION, name); |
3031 } | 3042 } |
3032 | 3043 |
3033 | 3044 |
3034 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3045 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
3035 JSObject* holder, | 3046 JSObject* holder, |
3036 String* name) { | 3047 String* name) { |
3037 // ----------- S t a t e ------------- | 3048 // ----------- S t a t e ------------- |
3038 // -- eax : key | 3049 // -- eax : key |
3039 // -- edx : receiver | 3050 // -- edx : receiver |
3040 // -- esp[0] : return address | 3051 // -- esp[0] : return address |
3041 // ----------------------------------- | 3052 // ----------------------------------- |
3042 Label miss; | 3053 Label miss; |
3043 | 3054 |
3044 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); | 3055 __ IncrementCounter(COUNTERS->keyed_load_interceptor(), 1); |
3045 | 3056 |
3046 // Check that the name has not changed. | 3057 // Check that the name has not changed. |
3047 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3058 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3048 __ j(not_equal, &miss, not_taken); | 3059 __ j(not_equal, &miss, not_taken); |
3049 | 3060 |
3050 LookupResult lookup; | 3061 LookupResult lookup; |
3051 LookupPostInterceptor(holder, name, &lookup); | 3062 LookupPostInterceptor(holder, name, &lookup); |
3052 GenerateLoadInterceptor(receiver, | 3063 GenerateLoadInterceptor(receiver, |
3053 holder, | 3064 holder, |
3054 &lookup, | 3065 &lookup, |
3055 edx, | 3066 edx, |
3056 eax, | 3067 eax, |
3057 ecx, | 3068 ecx, |
3058 ebx, | 3069 ebx, |
3059 edi, | 3070 edi, |
3060 name, | 3071 name, |
3061 &miss); | 3072 &miss); |
3062 __ bind(&miss); | 3073 __ bind(&miss); |
3063 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); | 3074 __ DecrementCounter(COUNTERS->keyed_load_interceptor(), 1); |
3064 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3075 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3065 | 3076 |
3066 // Return the generated code. | 3077 // Return the generated code. |
3067 return GetCode(INTERCEPTOR, name); | 3078 return GetCode(INTERCEPTOR, name); |
3068 } | 3079 } |
3069 | 3080 |
3070 | 3081 |
3071 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3082 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { |
3072 // ----------- S t a t e ------------- | 3083 // ----------- S t a t e ------------- |
3073 // -- eax : key | 3084 // -- eax : key |
3074 // -- edx : receiver | 3085 // -- edx : receiver |
3075 // -- esp[0] : return address | 3086 // -- esp[0] : return address |
3076 // ----------------------------------- | 3087 // ----------------------------------- |
3077 Label miss; | 3088 Label miss; |
3078 | 3089 |
3079 __ IncrementCounter(&Counters::keyed_load_array_length, 1); | 3090 __ IncrementCounter(COUNTERS->keyed_load_array_length(), 1); |
3080 | 3091 |
3081 // Check that the name has not changed. | 3092 // Check that the name has not changed. |
3082 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3093 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3083 __ j(not_equal, &miss, not_taken); | 3094 __ j(not_equal, &miss, not_taken); |
3084 | 3095 |
3085 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3096 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
3086 __ bind(&miss); | 3097 __ bind(&miss); |
3087 __ DecrementCounter(&Counters::keyed_load_array_length, 1); | 3098 __ DecrementCounter(COUNTERS->keyed_load_array_length(), 1); |
3088 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3099 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3089 | 3100 |
3090 // Return the generated code. | 3101 // Return the generated code. |
3091 return GetCode(CALLBACKS, name); | 3102 return GetCode(CALLBACKS, name); |
3092 } | 3103 } |
3093 | 3104 |
3094 | 3105 |
3095 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3106 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
3096 // ----------- S t a t e ------------- | 3107 // ----------- S t a t e ------------- |
3097 // -- eax : key | 3108 // -- eax : key |
3098 // -- edx : receiver | 3109 // -- edx : receiver |
3099 // -- esp[0] : return address | 3110 // -- esp[0] : return address |
3100 // ----------------------------------- | 3111 // ----------------------------------- |
3101 Label miss; | 3112 Label miss; |
3102 | 3113 |
3103 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | 3114 __ IncrementCounter(COUNTERS->keyed_load_string_length(), 1); |
3104 | 3115 |
3105 // Check that the name has not changed. | 3116 // Check that the name has not changed. |
3106 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3117 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3107 __ j(not_equal, &miss, not_taken); | 3118 __ j(not_equal, &miss, not_taken); |
3108 | 3119 |
3109 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3120 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
3110 __ bind(&miss); | 3121 __ bind(&miss); |
3111 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | 3122 __ DecrementCounter(COUNTERS->keyed_load_string_length(), 1); |
3112 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3123 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3113 | 3124 |
3114 // Return the generated code. | 3125 // Return the generated code. |
3115 return GetCode(CALLBACKS, name); | 3126 return GetCode(CALLBACKS, name); |
3116 } | 3127 } |
3117 | 3128 |
3118 | 3129 |
3119 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3130 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
3120 // ----------- S t a t e ------------- | 3131 // ----------- S t a t e ------------- |
3121 // -- eax : key | 3132 // -- eax : key |
3122 // -- edx : receiver | 3133 // -- edx : receiver |
3123 // -- esp[0] : return address | 3134 // -- esp[0] : return address |
3124 // ----------------------------------- | 3135 // ----------------------------------- |
3125 Label miss; | 3136 Label miss; |
3126 | 3137 |
3127 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1); | 3138 __ IncrementCounter(COUNTERS->keyed_load_function_prototype(), 1); |
3128 | 3139 |
3129 // Check that the name has not changed. | 3140 // Check that the name has not changed. |
3130 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3141 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3131 __ j(not_equal, &miss, not_taken); | 3142 __ j(not_equal, &miss, not_taken); |
3132 | 3143 |
3133 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3144 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
3134 __ bind(&miss); | 3145 __ bind(&miss); |
3135 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1); | 3146 __ DecrementCounter(COUNTERS->keyed_load_function_prototype(), 1); |
3136 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3147 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3137 | 3148 |
3138 // Return the generated code. | 3149 // Return the generated code. |
3139 return GetCode(CALLBACKS, name); | 3150 return GetCode(CALLBACKS, name); |
3140 } | 3151 } |
3141 | 3152 |
3142 | 3153 |
3143 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3154 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
3144 // ----------- S t a t e ------------- | 3155 // ----------- S t a t e ------------- |
3145 // -- eax : key | 3156 // -- eax : key |
(...skipping 19 matching lines...) Expand all Loading... |
3165 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3176 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3166 __ AssertFastElements(ecx); | 3177 __ AssertFastElements(ecx); |
3167 | 3178 |
3168 // Check that the key is within bounds. | 3179 // Check that the key is within bounds. |
3169 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3180 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3170 __ j(above_equal, &miss, not_taken); | 3181 __ j(above_equal, &miss, not_taken); |
3171 | 3182 |
3172 // Load the result and make sure it's not the hole. | 3183 // Load the result and make sure it's not the hole. |
3173 __ mov(ebx, Operand(ecx, eax, times_2, | 3184 __ mov(ebx, Operand(ecx, eax, times_2, |
3174 FixedArray::kHeaderSize - kHeapObjectTag)); | 3185 FixedArray::kHeaderSize - kHeapObjectTag)); |
3175 __ cmp(ebx, Factory::the_hole_value()); | 3186 __ cmp(ebx, FACTORY->the_hole_value()); |
3176 __ j(equal, &miss, not_taken); | 3187 __ j(equal, &miss, not_taken); |
3177 __ mov(eax, ebx); | 3188 __ mov(eax, ebx); |
3178 __ ret(0); | 3189 __ ret(0); |
3179 | 3190 |
3180 __ bind(&miss); | 3191 __ bind(&miss); |
3181 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3192 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3182 | 3193 |
3183 // Return the generated code. | 3194 // Return the generated code. |
3184 return GetCode(NORMAL, NULL); | 3195 return GetCode(NORMAL, NULL); |
3185 } | 3196 } |
3186 | 3197 |
3187 | 3198 |
3188 // Specialized stub for constructing objects from functions which only have only | 3199 // Specialized stub for constructing objects from functions which only have only |
3189 // simple assignments of the form this.x = ...; in their body. | 3200 // simple assignments of the form this.x = ...; in their body. |
3190 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3201 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3191 // ----------- S t a t e ------------- | 3202 // ----------- S t a t e ------------- |
3192 // -- eax : argc | 3203 // -- eax : argc |
3193 // -- edi : constructor | 3204 // -- edi : constructor |
3194 // -- esp[0] : return address | 3205 // -- esp[0] : return address |
3195 // -- esp[4] : last argument | 3206 // -- esp[4] : last argument |
3196 // ----------------------------------- | 3207 // ----------------------------------- |
3197 Label generic_stub_call; | 3208 Label generic_stub_call; |
3198 #ifdef ENABLE_DEBUGGER_SUPPORT | 3209 #ifdef ENABLE_DEBUGGER_SUPPORT |
3199 // Check to see whether there are any break points in the function code. If | 3210 // Check to see whether there are any break points in the function code. If |
3200 // there are jump to the generic constructor stub which calls the actual | 3211 // there are jump to the generic constructor stub which calls the actual |
3201 // code for the function thereby hitting the break points. | 3212 // code for the function thereby hitting the break points. |
3202 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3213 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
3203 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3214 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
3204 __ cmp(ebx, Factory::undefined_value()); | 3215 __ cmp(ebx, FACTORY->undefined_value()); |
3205 __ j(not_equal, &generic_stub_call, not_taken); | 3216 __ j(not_equal, &generic_stub_call, not_taken); |
3206 #endif | 3217 #endif |
3207 | 3218 |
3208 // Load the initial map and verify that it is in fact a map. | 3219 // Load the initial map and verify that it is in fact a map. |
3209 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3220 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
3210 // Will both indicate a NULL and a Smi. | 3221 // Will both indicate a NULL and a Smi. |
3211 __ test(ebx, Immediate(kSmiTagMask)); | 3222 __ test(ebx, Immediate(kSmiTagMask)); |
3212 __ j(zero, &generic_stub_call); | 3223 __ j(zero, &generic_stub_call); |
3213 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3224 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
3214 __ j(not_equal, &generic_stub_call); | 3225 __ j(not_equal, &generic_stub_call); |
(...skipping 16 matching lines...) Expand all Loading... |
3231 edx, | 3242 edx, |
3232 ecx, | 3243 ecx, |
3233 no_reg, | 3244 no_reg, |
3234 &generic_stub_call, | 3245 &generic_stub_call, |
3235 NO_ALLOCATION_FLAGS); | 3246 NO_ALLOCATION_FLAGS); |
3236 | 3247 |
3237 // Allocated the JSObject, now initialize the fields and add the heap tag. | 3248 // Allocated the JSObject, now initialize the fields and add the heap tag. |
3238 // ebx: initial map | 3249 // ebx: initial map |
3239 // edx: JSObject (untagged) | 3250 // edx: JSObject (untagged) |
3240 __ mov(Operand(edx, JSObject::kMapOffset), ebx); | 3251 __ mov(Operand(edx, JSObject::kMapOffset), ebx); |
3241 __ mov(ebx, Factory::empty_fixed_array()); | 3252 __ mov(ebx, FACTORY->empty_fixed_array()); |
3242 __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); | 3253 __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); |
3243 __ mov(Operand(edx, JSObject::kElementsOffset), ebx); | 3254 __ mov(Operand(edx, JSObject::kElementsOffset), ebx); |
3244 | 3255 |
3245 // Push the allocated object to the stack. This is the object that will be | 3256 // Push the allocated object to the stack. This is the object that will be |
3246 // returned (after it is tagged). | 3257 // returned (after it is tagged). |
3247 __ push(edx); | 3258 __ push(edx); |
3248 | 3259 |
3249 // eax: argc | 3260 // eax: argc |
3250 // edx: JSObject (untagged) | 3261 // edx: JSObject (untagged) |
3251 // Load the address of the first in-object property into edx. | 3262 // Load the address of the first in-object property into edx. |
3252 __ lea(edx, Operand(edx, JSObject::kHeaderSize)); | 3263 __ lea(edx, Operand(edx, JSObject::kHeaderSize)); |
3253 // Calculate the location of the first argument. The stack contains the | 3264 // Calculate the location of the first argument. The stack contains the |
3254 // allocated object and the return address on top of the argc arguments. | 3265 // allocated object and the return address on top of the argc arguments. |
3255 __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); | 3266 __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); |
3256 | 3267 |
3257 // Use edi for holding undefined which is used in several places below. | 3268 // Use edi for holding undefined which is used in several places below. |
3258 __ mov(edi, Factory::undefined_value()); | 3269 __ mov(edi, FACTORY->undefined_value()); |
3259 | 3270 |
3260 // eax: argc | 3271 // eax: argc |
3261 // ecx: first argument | 3272 // ecx: first argument |
3262 // edx: first in-object property of the JSObject | 3273 // edx: first in-object property of the JSObject |
3263 // edi: undefined | 3274 // edi: undefined |
3264 // Fill the initialized properties with a constant value or a passed argument | 3275 // Fill the initialized properties with a constant value or a passed argument |
3265 // depending on the this.x = ...; assignment in the function. | 3276 // depending on the this.x = ...; assignment in the function. |
3266 SharedFunctionInfo* shared = function->shared(); | 3277 SharedFunctionInfo* shared = function->shared(); |
3267 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3278 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
3268 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3279 if (shared->IsThisPropertyAssignmentArgument(i)) { |
3269 // Check if the argument assigned to the property is actually passed. | 3280 // Check if the argument assigned to the property is actually passed. |
3270 // If argument is not passed the property is set to undefined, | 3281 // If argument is not passed the property is set to undefined, |
3271 // otherwise find it on the stack. | 3282 // otherwise find it on the stack. |
3272 int arg_number = shared->GetThisPropertyAssignmentArgument(i); | 3283 int arg_number = shared->GetThisPropertyAssignmentArgument(i); |
3273 __ mov(ebx, edi); | 3284 __ mov(ebx, edi); |
3274 __ cmp(eax, arg_number); | 3285 __ cmp(eax, arg_number); |
3275 if (CpuFeatures::IsSupported(CMOV)) { | 3286 if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) { |
3276 CpuFeatures::Scope use_cmov(CMOV); | 3287 CpuFeatures::Scope use_cmov(CMOV); |
3277 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); | 3288 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); |
3278 } else { | 3289 } else { |
3279 Label not_passed; | 3290 Label not_passed; |
3280 __ j(below_equal, ¬_passed); | 3291 __ j(below_equal, ¬_passed); |
3281 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); | 3292 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); |
3282 __ bind(¬_passed); | 3293 __ bind(¬_passed); |
3283 } | 3294 } |
3284 // Store value in the property. | 3295 // Store value in the property. |
3285 __ mov(Operand(edx, i * kPointerSize), ebx); | 3296 __ mov(Operand(edx, i * kPointerSize), ebx); |
(...skipping 14 matching lines...) Expand all Loading... |
3300 | 3311 |
3301 // Move argc to ebx and retrieve and tag the JSObject to return. | 3312 // Move argc to ebx and retrieve and tag the JSObject to return. |
3302 __ mov(ebx, eax); | 3313 __ mov(ebx, eax); |
3303 __ pop(eax); | 3314 __ pop(eax); |
3304 __ or_(Operand(eax), Immediate(kHeapObjectTag)); | 3315 __ or_(Operand(eax), Immediate(kHeapObjectTag)); |
3305 | 3316 |
3306 // Remove caller arguments and receiver from the stack and return. | 3317 // Remove caller arguments and receiver from the stack and return. |
3307 __ pop(ecx); | 3318 __ pop(ecx); |
3308 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3319 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
3309 __ push(ecx); | 3320 __ push(ecx); |
3310 __ IncrementCounter(&Counters::constructed_objects, 1); | 3321 __ IncrementCounter(COUNTERS->constructed_objects(), 1); |
3311 __ IncrementCounter(&Counters::constructed_objects_stub, 1); | 3322 __ IncrementCounter(COUNTERS->constructed_objects_stub(), 1); |
3312 __ ret(0); | 3323 __ ret(0); |
3313 | 3324 |
3314 // Jump to the generic stub in case the specialized code cannot handle the | 3325 // Jump to the generic stub in case the specialized code cannot handle the |
3315 // construction. | 3326 // construction. |
3316 __ bind(&generic_stub_call); | 3327 __ bind(&generic_stub_call); |
3317 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); | 3328 Code* code = Isolate::Current()->builtins()->builtin( |
| 3329 Builtins::JSConstructStubGeneric); |
3318 Handle<Code> generic_construct_stub(code); | 3330 Handle<Code> generic_construct_stub(code); |
3319 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3331 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
3320 | 3332 |
3321 // Return the generated code. | 3333 // Return the generated code. |
3322 return GetCode(); | 3334 return GetCode(); |
3323 } | 3335 } |
3324 | 3336 |
3325 | 3337 |
3326 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3338 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3327 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3339 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3448 | 3460 |
3449 // If we fail allocation of the HeapNumber, we still have a value on | 3461 // If we fail allocation of the HeapNumber, we still have a value on |
3450 // top of the FPU stack. Remove it. | 3462 // top of the FPU stack. Remove it. |
3451 __ bind(&failed_allocation); | 3463 __ bind(&failed_allocation); |
3452 __ ffree(); | 3464 __ ffree(); |
3453 __ fincstp(); | 3465 __ fincstp(); |
3454 // Fall through to slow case. | 3466 // Fall through to slow case. |
3455 | 3467 |
3456 // Slow case: Jump to runtime. | 3468 // Slow case: Jump to runtime. |
3457 __ bind(&slow); | 3469 __ bind(&slow); |
3458 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); | 3470 __ IncrementCounter(COUNTERS->keyed_load_external_array_slow(), 1); |
3459 // ----------- S t a t e ------------- | 3471 // ----------- S t a t e ------------- |
3460 // -- eax : key | 3472 // -- eax : key |
3461 // -- edx : receiver | 3473 // -- edx : receiver |
3462 // -- esp[0] : return address | 3474 // -- esp[0] : return address |
3463 // ----------------------------------- | 3475 // ----------------------------------- |
3464 | 3476 |
3465 __ pop(ebx); | 3477 __ pop(ebx); |
3466 __ push(edx); // receiver | 3478 __ push(edx); // receiver |
3467 __ push(eax); // name | 3479 __ push(eax); // name |
3468 __ push(ebx); // return address | 3480 __ push(ebx); // return address |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3561 | 3573 |
3562 // TODO(danno): handle heap number -> pixel array conversion | 3574 // TODO(danno): handle heap number -> pixel array conversion |
3563 if (array_type != kExternalPixelArray) { | 3575 if (array_type != kExternalPixelArray) { |
3564 __ bind(&check_heap_number); | 3576 __ bind(&check_heap_number); |
3565 // eax: value | 3577 // eax: value |
3566 // edx: receiver | 3578 // edx: receiver |
3567 // ecx: key | 3579 // ecx: key |
3568 // edi: elements array | 3580 // edi: elements array |
3569 // ebx: untagged index | 3581 // ebx: untagged index |
3570 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3582 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3571 Immediate(Factory::heap_number_map())); | 3583 Immediate(FACTORY->heap_number_map())); |
3572 __ j(not_equal, &slow); | 3584 __ j(not_equal, &slow); |
3573 | 3585 |
3574 // The WebGL specification leaves the behavior of storing NaN and | 3586 // The WebGL specification leaves the behavior of storing NaN and |
3575 // +/-Infinity into integer arrays basically undefined. For more | 3587 // +/-Infinity into integer arrays basically undefined. For more |
3576 // reproducible behavior, convert these to zero. | 3588 // reproducible behavior, convert these to zero. |
3577 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3589 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3578 // ebx: untagged index | 3590 // ebx: untagged index |
3579 // edi: base pointer of external storage | 3591 // edi: base pointer of external storage |
3580 if (array_type == kExternalFloatArray) { | 3592 if (array_type == kExternalFloatArray) { |
3581 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3593 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3582 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3594 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3583 __ ret(0); | 3595 __ ret(0); |
3584 } else { | 3596 } else { |
3585 // Perform float-to-int conversion with truncation (round-to-zero) | 3597 // Perform float-to-int conversion with truncation (round-to-zero) |
3586 // behavior. | 3598 // behavior. |
3587 | 3599 |
3588 // For the moment we make the slow call to the runtime on | 3600 // For the moment we make the slow call to the runtime on |
3589 // processors that don't support SSE2. The code in IntegerConvert | 3601 // processors that don't support SSE2. The code in IntegerConvert |
3590 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3602 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3591 // conversion failure case does not need to be handled. | 3603 // conversion failure case does not need to be handled. |
3592 if (CpuFeatures::IsSupported(SSE2)) { | 3604 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { |
3593 if (array_type != kExternalIntArray && | 3605 if (array_type != kExternalIntArray && |
3594 array_type != kExternalUnsignedIntArray) { | 3606 array_type != kExternalUnsignedIntArray) { |
3595 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3607 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); |
3596 CpuFeatures::Scope scope(SSE2); | 3608 CpuFeatures::Scope scope(SSE2); |
3597 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3609 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3598 // ecx: untagged integer value | 3610 // ecx: untagged integer value |
3599 switch (array_type) { | 3611 switch (array_type) { |
3600 case kExternalPixelArray: | 3612 case kExternalPixelArray: |
3601 { // Clamp the value to [0..255]. | 3613 { // Clamp the value to [0..255]. |
3602 NearLabel done; | 3614 NearLabel done; |
3603 __ test(ecx, Immediate(0xFFFFFF00)); | 3615 __ test(ecx, Immediate(0xFFFFFF00)); |
3604 __ j(zero, &done); | 3616 __ j(zero, &done); |
3605 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3617 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3606 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3618 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3607 __ bind(&done); | 3619 __ bind(&done); |
3608 } | 3620 } |
3609 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3621 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3610 case kExternalByteArray: | 3622 case kExternalByteArray: |
3611 case kExternalUnsignedByteArray: | 3623 case kExternalUnsignedByteArray: |
3612 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3624 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3613 break; | 3625 break; |
3614 case kExternalShortArray: | 3626 case kExternalShortArray: |
3615 case kExternalUnsignedShortArray: | 3627 case kExternalUnsignedShortArray: |
3616 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3628 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3617 break; | 3629 break; |
3618 default: | 3630 default: |
3619 UNREACHABLE(); | 3631 UNREACHABLE(); |
3620 break; | 3632 break; |
3621 } | 3633 } |
3622 } else { | 3634 } else { |
3623 if (CpuFeatures::IsSupported(SSE3)) { | 3635 if (Isolate::Current()->cpu_features()->IsSupported(SSE3)) { |
3624 CpuFeatures::Scope scope(SSE3); | 3636 CpuFeatures::Scope scope(SSE3); |
3625 // fisttp stores values as signed integers. To represent the | 3637 // fisttp stores values as signed integers. To represent the |
3626 // entire range of int and unsigned int arrays, store as a | 3638 // entire range of int and unsigned int arrays, store as a |
3627 // 64-bit int and discard the high 32 bits. | 3639 // 64-bit int and discard the high 32 bits. |
3628 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3640 // If the value is NaN or +/-infinity, the result is 0x80000000, |
3629 // which is automatically zero when taken mod 2^n, n < 32. | 3641 // which is automatically zero when taken mod 2^n, n < 32. |
3630 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3642 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3631 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3643 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
3632 __ fisttp_d(Operand(esp, 0)); | 3644 __ fisttp_d(Operand(esp, 0)); |
3633 __ pop(ecx); | 3645 __ pop(ecx); |
3634 __ add(Operand(esp), Immediate(kPointerSize)); | 3646 __ add(Operand(esp), Immediate(kPointerSize)); |
3635 } else { | 3647 } else { |
3636 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3648 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); |
3637 CpuFeatures::Scope scope(SSE2); | 3649 CpuFeatures::Scope scope(SSE2); |
3638 // We can easily implement the correct rounding behavior for the | 3650 // We can easily implement the correct rounding behavior for the |
3639 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3651 // range [0, 2^31-1]. For the time being, to keep this code simple, |
3640 // make the slow runtime call for values outside this range. | 3652 // make the slow runtime call for values outside this range. |
3641 // Note: we could do better for signed int arrays. | 3653 // Note: we could do better for signed int arrays. |
3642 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3654 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
3643 // We will need the key if we have to make the slow runtime call. | 3655 // We will need the key if we have to make the slow runtime call. |
3644 __ push(ecx); | 3656 __ push(ecx); |
3645 __ LoadPowerOf2(xmm1, ecx, 31); | 3657 __ LoadPowerOf2(xmm1, ecx, 31); |
3646 __ pop(ecx); | 3658 __ pop(ecx); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3679 | 3691 |
3680 return GetCode(flags); | 3692 return GetCode(flags); |
3681 } | 3693 } |
3682 | 3694 |
3683 | 3695 |
3684 #undef __ | 3696 #undef __ |
3685 | 3697 |
3686 } } // namespace v8::internal | 3698 } } // namespace v8::internal |
3687 | 3699 |
3688 #endif // V8_TARGET_ARCH_IA32 | 3700 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |