| 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 |