| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #define __ ACCESS_MASM(masm) | 43 #define __ ACCESS_MASM(masm) |
| 44 | 44 |
| 45 | 45 |
| 46 // Helper function used to load a property from a dictionary backing storage. | 46 // Helper function used to load a property from a dictionary backing storage. |
| 47 // This function may return false negatives, so miss_label | 47 // This function may return false negatives, so miss_label |
| 48 // must always call a backup property load that is complete. | 48 // must always call a backup property load that is complete. |
| 49 // This function is safe to call if the receiver has fast properties, | 49 // This function is safe to call if the receiver has fast properties, |
| 50 // or if name is not a symbol, and will jump to the miss_label in that case. | 50 // or if name is not a symbol, and will jump to the miss_label in that case. |
| 51 static void GenerateDictionaryLoad(MacroAssembler* masm, | 51 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 52 Label* miss_label, | 52 Label* miss_label, |
| 53 Register receiver, |
| 54 Register name, |
| 53 Register r0, | 55 Register r0, |
| 54 Register r1, | 56 Register r1, |
| 55 Register r2, | 57 Register r2, |
| 56 Register name, | |
| 57 DictionaryCheck check_dictionary) { | 58 DictionaryCheck check_dictionary) { |
| 58 // Register use: | 59 // Register use: |
| 59 // | 60 // |
| 61 // name - holds the name of the property and is unchanged. |
| 62 // receiver - holds the receiver and is unchanged. |
| 63 // Scratch registers: |
| 60 // r0 - used to hold the property dictionary. | 64 // r0 - used to hold the property dictionary. |
| 61 // | 65 // |
| 62 // r1 - initially the receiver | 66 // r1 - used for the index into the property dictionary |
| 63 // - used for the index into the property dictionary | |
| 64 // - holds the result on exit. | 67 // - holds the result on exit. |
| 65 // | 68 // |
| 66 // r2 - used to hold the capacity of the property dictionary. | 69 // r2 - used to hold the capacity of the property dictionary. |
| 67 // | |
| 68 // name - holds the name of the property and is unchanged. | |
| 69 | 70 |
| 70 Label done; | 71 Label done; |
| 71 | 72 |
| 72 // Check for the absence of an interceptor. | 73 // Check for the absence of an interceptor. |
| 73 // Load the map into r0. | 74 // Load the map into r0. |
| 74 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset)); | 75 __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset)); |
| 75 // Test the has_named_interceptor bit in the map. | 76 // Test the has_named_interceptor bit in the map. |
| 76 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), | 77 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), |
| 77 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); | 78 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); |
| 78 | 79 |
| 79 // Jump to miss if the interceptor bit is set. | 80 // Jump to miss if the interceptor bit is set. |
| 80 __ j(not_zero, miss_label, not_taken); | 81 __ j(not_zero, miss_label, not_taken); |
| 81 | 82 |
| 82 // Bail out if we have a JS global proxy object. | 83 // Bail out if we have a JS global proxy object. |
| 83 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); | 84 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); |
| 84 __ cmp(r0, JS_GLOBAL_PROXY_TYPE); | 85 __ cmp(r0, JS_GLOBAL_PROXY_TYPE); |
| 85 __ j(equal, miss_label, not_taken); | 86 __ j(equal, miss_label, not_taken); |
| 86 | 87 |
| 87 // Possible work-around for http://crbug.com/16276. | 88 // Possible work-around for http://crbug.com/16276. |
| 88 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); | 89 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); |
| 89 __ j(equal, miss_label, not_taken); | 90 __ j(equal, miss_label, not_taken); |
| 90 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); | 91 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); |
| 91 __ j(equal, miss_label, not_taken); | 92 __ j(equal, miss_label, not_taken); |
| 92 | 93 |
| 93 // Load properties array. | 94 // Load properties array. |
| 94 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); | 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 95 | 96 |
| 96 // Check that the properties array is a dictionary. | 97 // Check that the properties array is a dictionary. |
| 97 if (check_dictionary == CHECK_DICTIONARY) { | 98 if (check_dictionary == CHECK_DICTIONARY) { |
| 98 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), | 99 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), |
| 99 Immediate(Factory::hash_table_map())); | 100 Immediate(Factory::hash_table_map())); |
| 100 __ j(not_equal, miss_label); | 101 __ j(not_equal, miss_label); |
| 101 } | 102 } |
| 102 | 103 |
| 103 // Compute the capacity mask. | 104 // Compute the capacity mask. |
| 104 const int kCapacityOffset = | 105 const int kCapacityOffset = |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 | 153 |
| 153 | 154 |
| 154 // The offset from the inlined patch site to the start of the | 155 // The offset from the inlined patch site to the start of the |
| 155 // inlined load instruction. It is 7 bytes (test eax, imm) plus | 156 // inlined load instruction. It is 7 bytes (test eax, imm) plus |
| 156 // 6 bytes (jne slow_label). | 157 // 6 bytes (jne slow_label). |
| 157 const int LoadIC::kOffsetToLoadInstruction = 13; | 158 const int LoadIC::kOffsetToLoadInstruction = 13; |
| 158 | 159 |
| 159 | 160 |
| 160 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 161 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 161 // ----------- S t a t e ------------- | 162 // ----------- S t a t e ------------- |
| 163 // -- eax : receiver |
| 162 // -- ecx : name | 164 // -- ecx : name |
| 163 // -- esp[0] : return address | 165 // -- esp[0] : return address |
| 164 // -- esp[4] : receiver | |
| 165 // ----------------------------------- | 166 // ----------------------------------- |
| 166 Label miss; | 167 Label miss; |
| 167 | 168 |
| 168 __ mov(eax, Operand(esp, kPointerSize)); | |
| 169 | |
| 170 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); | 169 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); |
| 171 __ bind(&miss); | 170 __ bind(&miss); |
| 172 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 171 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 173 } | 172 } |
| 174 | 173 |
| 175 | 174 |
| 176 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 175 void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
| 177 // ----------- S t a t e ------------- | 176 // ----------- S t a t e ------------- |
| 177 // -- eax : receiver |
| 178 // -- ecx : name | 178 // -- ecx : name |
| 179 // -- esp[0] : return address | 179 // -- esp[0] : return address |
| 180 // -- esp[4] : receiver | |
| 181 // ----------------------------------- | 180 // ----------------------------------- |
| 182 Label miss; | 181 Label miss; |
| 183 | 182 |
| 184 __ mov(eax, Operand(esp, kPointerSize)); | 183 StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); |
| 185 | |
| 186 StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss); | |
| 187 __ bind(&miss); | 184 __ bind(&miss); |
| 188 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 185 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 189 } | 186 } |
| 190 | 187 |
| 191 | 188 |
| 192 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { | 189 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { |
| 193 // ----------- S t a t e ------------- | 190 // ----------- S t a t e ------------- |
| 191 // -- eax : receiver |
| 194 // -- ecx : name | 192 // -- ecx : name |
| 195 // -- esp[0] : return address | 193 // -- esp[0] : return address |
| 196 // -- esp[4] : receiver | |
| 197 // ----------------------------------- | 194 // ----------------------------------- |
| 198 Label miss; | 195 Label miss; |
| 199 | 196 |
| 200 __ mov(eax, Operand(esp, kPointerSize)); | |
| 201 | |
| 202 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); | 197 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); |
| 203 __ bind(&miss); | 198 __ bind(&miss); |
| 204 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 199 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 205 } | 200 } |
| 206 | 201 |
| 207 | 202 |
| 208 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 203 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 209 // ----------- S t a t e ------------- | 204 // ----------- S t a t e ------------- |
| 205 // -- eax : key |
| 206 // -- edx : receiver |
| 210 // -- esp[0] : return address | 207 // -- esp[0] : return address |
| 211 // -- esp[4] : name | |
| 212 // -- esp[8] : receiver | |
| 213 // ----------------------------------- | 208 // ----------------------------------- |
| 214 Label slow, check_string, index_int, index_string; | 209 Label slow, check_string, index_int, index_string; |
| 215 Label check_pixel_array, probe_dictionary; | 210 Label check_pixel_array, probe_dictionary; |
| 216 | 211 |
| 217 // Load name and receiver. | |
| 218 __ mov(eax, Operand(esp, kPointerSize)); | |
| 219 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 220 | |
| 221 // Check that the object isn't a smi. | 212 // Check that the object isn't a smi. |
| 222 __ test(ecx, Immediate(kSmiTagMask)); | 213 __ test(edx, Immediate(kSmiTagMask)); |
| 223 __ j(zero, &slow, not_taken); | 214 __ j(zero, &slow, not_taken); |
| 224 | 215 |
| 225 // Get the map of the receiver. | 216 // Get the map of the receiver. |
| 226 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 217 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 227 | 218 |
| 228 // Check bit field. | 219 // Check bit field. |
| 229 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); | 220 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); |
| 230 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); | 221 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); |
| 231 __ j(not_zero, &slow, not_taken); | 222 __ j(not_zero, &slow, not_taken); |
| 232 // Check that the object is some kind of JS object EXCEPT JS Value type. | 223 // Check that the object is some kind of JS object EXCEPT JS Value type. |
| 233 // In the case that the object is a value-wrapper object, | 224 // In the case that the object is a value-wrapper object, |
| 234 // we enter the runtime system to make sure that indexing | 225 // we enter the runtime system to make sure that indexing |
| 235 // into string objects work as intended. | 226 // into string objects work as intended. |
| 236 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 227 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 237 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 228 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); |
| 238 __ cmp(edx, JS_OBJECT_TYPE); | 229 __ j(below, &slow, not_taken); |
| 239 __ j(less, &slow, not_taken); | |
| 240 // Check that the key is a smi. | 230 // Check that the key is a smi. |
| 241 __ test(eax, Immediate(kSmiTagMask)); | 231 __ test(eax, Immediate(kSmiTagMask)); |
| 242 __ j(not_zero, &check_string, not_taken); | 232 __ j(not_zero, &check_string, not_taken); |
| 243 __ sar(eax, kSmiTagSize); | 233 __ mov(ebx, eax); |
| 234 __ SmiUntag(ebx); |
| 244 // Get the elements array of the object. | 235 // Get the elements array of the object. |
| 245 __ bind(&index_int); | 236 __ bind(&index_int); |
| 246 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); | 237 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
| 247 // Check that the object is in fast mode (not dictionary). | 238 // Check that the object is in fast mode (not dictionary). |
| 248 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 239 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); |
| 249 Immediate(Factory::fixed_array_map())); | |
| 250 __ j(not_equal, &check_pixel_array); | |
| 251 // Check that the key (index) is within bounds. | 240 // Check that the key (index) is within bounds. |
| 252 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 241 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| 253 __ j(above_equal, &slow); | 242 __ j(above_equal, &slow); |
| 254 // Fast case: Do the load. | 243 // Fast case: Do the load. |
| 255 __ mov(eax, | 244 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); |
| 256 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); | 245 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); |
| 257 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | |
| 258 // In case the loaded value is the_hole we have to consult GetProperty | 246 // In case the loaded value is the_hole we have to consult GetProperty |
| 259 // to ensure the prototype chain is searched. | 247 // to ensure the prototype chain is searched. |
| 260 __ j(equal, &slow); | 248 __ j(equal, &slow); |
| 249 __ mov(eax, ecx); |
| 261 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 250 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
| 262 __ ret(0); | 251 __ ret(0); |
| 263 | 252 |
| 253 __ bind(&check_pixel_array); |
| 264 // Check whether the elements is a pixel array. | 254 // Check whether the elements is a pixel array. |
| 265 // eax: untagged index | 255 // edx: receiver |
| 266 // ecx: elements array | 256 // ebx: untagged index |
| 267 __ bind(&check_pixel_array); | 257 // eax: key |
| 268 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 258 // ecx: elements |
| 269 Immediate(Factory::pixel_array_map())); | 259 __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true); |
| 270 __ j(not_equal, &slow); | 260 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
| 271 __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset)); | |
| 272 __ j(above_equal, &slow); | 261 __ j(above_equal, &slow); |
| 273 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 262 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
| 274 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | 263 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); |
| 275 __ shl(eax, kSmiTagSize); | 264 __ SmiTag(eax); |
| 276 __ ret(0); | 265 __ ret(0); |
| 277 | 266 |
| 278 // Slow case: Load name and receiver from stack and jump to runtime. | |
| 279 __ bind(&slow); | 267 __ bind(&slow); |
| 268 // Slow case: jump to runtime. |
| 269 // edx: receiver |
| 270 // eax: key |
| 280 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 271 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
| 281 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 272 GenerateRuntimeGetProperty(masm); |
| 282 | 273 |
| 283 __ bind(&check_string); | 274 __ bind(&check_string); |
| 284 // The key is not a smi. | 275 // The key is not a smi. |
| 285 // Is it a string? | 276 // Is it a string? |
| 286 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 277 // edx: receiver |
| 278 // eax: key |
| 279 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); |
| 287 __ j(above_equal, &slow); | 280 __ j(above_equal, &slow); |
| 288 // Is the string an array index, with cached numeric value? | 281 // Is the string an array index, with cached numeric value? |
| 289 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); | 282 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); |
| 290 __ test(ebx, Immediate(String::kIsArrayIndexMask)); | 283 __ test(ebx, Immediate(String::kIsArrayIndexMask)); |
| 291 __ j(not_zero, &index_string, not_taken); | 284 __ j(not_zero, &index_string, not_taken); |
| 292 | 285 |
| 293 // Is the string a symbol? | 286 // Is the string a symbol? |
| 294 __ movzx_b(ebx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 287 __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 295 ASSERT(kSymbolTag != 0); | 288 ASSERT(kSymbolTag != 0); |
| 296 __ test(ebx, Immediate(kIsSymbolMask)); | 289 __ test(ebx, Immediate(kIsSymbolMask)); |
| 297 __ j(zero, &slow, not_taken); | 290 __ j(zero, &slow, not_taken); |
| 298 | 291 |
| 299 // If the receiver is a fast-case object, check the keyed lookup | 292 // If the receiver is a fast-case object, check the keyed lookup |
| 300 // cache. Otherwise probe the dictionary leaving result in ecx. | 293 // cache. Otherwise probe the dictionary. |
| 301 __ mov(ebx, FieldOperand(ecx, JSObject::kPropertiesOffset)); | 294 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); |
| 302 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 295 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 303 Immediate(Factory::hash_table_map())); | 296 Immediate(Factory::hash_table_map())); |
| 304 __ j(equal, &probe_dictionary); | 297 __ j(equal, &probe_dictionary); |
| 305 | 298 |
| 306 // Load the map of the receiver, compute the keyed lookup cache hash | 299 // Load the map of the receiver, compute the keyed lookup cache hash |
| 307 // based on 32 bits of the map pointer and the string hash. | 300 // based on 32 bits of the map pointer and the string hash. |
| 308 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); | 301 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 309 __ mov(edx, ebx); | 302 __ mov(ecx, ebx); |
| 310 __ shr(edx, KeyedLookupCache::kMapHashShift); | 303 __ shr(ecx, KeyedLookupCache::kMapHashShift); |
| 311 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 304 __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); |
| 312 __ shr(eax, String::kHashShift); | 305 __ shr(edi, String::kHashShift); |
| 313 __ xor_(edx, Operand(eax)); | 306 __ xor_(ecx, Operand(edi)); |
| 314 __ and_(edx, KeyedLookupCache::kCapacityMask); | 307 __ and_(ecx, KeyedLookupCache::kCapacityMask); |
| 315 | 308 |
| 316 // Load the key (consisting of map and symbol) from the cache and | 309 // Load the key (consisting of map and symbol) from the cache and |
| 317 // check for match. | 310 // check for match. |
| 318 ExternalReference cache_keys | 311 ExternalReference cache_keys |
| 319 = ExternalReference::keyed_lookup_cache_keys(); | 312 = ExternalReference::keyed_lookup_cache_keys(); |
| 320 __ mov(edi, edx); | 313 __ mov(edi, ecx); |
| 321 __ shl(edi, kPointerSizeLog2 + 1); | 314 __ shl(edi, kPointerSizeLog2 + 1); |
| 322 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); | 315 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); |
| 323 __ j(not_equal, &slow); | 316 __ j(not_equal, &slow); |
| 324 __ add(Operand(edi), Immediate(kPointerSize)); | 317 __ add(Operand(edi), Immediate(kPointerSize)); |
| 325 __ mov(edi, Operand::StaticArray(edi, times_1, cache_keys)); | 318 __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); |
| 326 __ cmp(edi, Operand(esp, kPointerSize)); | |
| 327 __ j(not_equal, &slow); | 319 __ j(not_equal, &slow); |
| 328 | 320 |
| 329 // Get field offset and check that it is an in-object property. | 321 // Get field offset and check that it is an in-object property. |
| 322 // edx : receiver |
| 323 // ebx : receiver's map |
| 324 // eax : key |
| 325 // ecx : lookup cache index |
| 330 ExternalReference cache_field_offsets | 326 ExternalReference cache_field_offsets |
| 331 = ExternalReference::keyed_lookup_cache_field_offsets(); | 327 = ExternalReference::keyed_lookup_cache_field_offsets(); |
| 332 __ mov(eax, | 328 __ mov(edi, |
| 333 Operand::StaticArray(edx, times_pointer_size, cache_field_offsets)); | 329 Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); |
| 334 __ movzx_b(edx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); | 330 __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); |
| 335 __ cmp(eax, Operand(edx)); | 331 __ cmp(edi, Operand(ecx)); |
| 336 __ j(above_equal, &slow); | 332 __ j(above_equal, &slow); |
| 337 | 333 |
| 338 // Load in-object property. | 334 // Load in-object property. |
| 339 __ sub(eax, Operand(edx)); | 335 __ sub(edi, Operand(ecx)); |
| 340 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceSizeOffset)); | 336 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); |
| 341 __ add(eax, Operand(edx)); | 337 __ add(ecx, Operand(edi)); |
| 342 __ mov(eax, FieldOperand(ecx, eax, times_pointer_size, 0)); | 338 __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); |
| 343 __ ret(0); | 339 __ ret(0); |
| 344 | 340 |
| 345 // Do a quick inline probe of the receiver's dictionary, if it | 341 // Do a quick inline probe of the receiver's dictionary, if it |
| 346 // exists. | 342 // exists. |
| 347 __ bind(&probe_dictionary); | 343 __ bind(&probe_dictionary); |
| 348 GenerateDictionaryLoad(masm, | 344 GenerateDictionaryLoad(masm, |
| 349 &slow, | 345 &slow, |
| 346 edx, |
| 347 eax, |
| 350 ebx, | 348 ebx, |
| 351 ecx, | 349 ecx, |
| 352 edx, | 350 edi, |
| 353 eax, | |
| 354 DICTIONARY_CHECK_DONE); | 351 DICTIONARY_CHECK_DONE); |
| 355 __ mov(eax, Operand(ecx)); | 352 __ mov(eax, Operand(ecx)); |
| 356 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 353 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
| 357 __ ret(0); | 354 __ ret(0); |
| 358 | 355 |
| 359 // If the hash field contains an array index pick it out. The assert checks | 356 // If the hash field contains an array index pick it out. The assert checks |
| 360 // that the constants for the maximum number of digits for an array index | 357 // that the constants for the maximum number of digits for an array index |
| 361 // cached in the hash field and the number of bits reserved for it does not | 358 // cached in the hash field and the number of bits reserved for it does not |
| 362 // conflict. | 359 // conflict. |
| 363 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 360 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
| 364 (1 << String::kArrayIndexValueBits)); | 361 (1 << String::kArrayIndexValueBits)); |
| 365 __ bind(&index_string); | 362 __ bind(&index_string); |
| 366 __ mov(eax, Operand(ebx)); | 363 __ and_(ebx, String::kArrayIndexHashMask); |
| 367 __ and_(eax, String::kArrayIndexHashMask); | 364 __ shr(ebx, String::kHashShift); |
| 368 __ shr(eax, String::kHashShift); | |
| 369 __ jmp(&index_int); | 365 __ jmp(&index_int); |
| 370 } | 366 } |
| 371 | 367 |
| 372 | 368 |
| 373 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 369 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 374 // ----------- S t a t e ------------- | 370 // ----------- S t a t e ------------- |
| 371 // -- eax : key |
| 372 // -- edx : receiver |
| 375 // -- esp[0] : return address | 373 // -- esp[0] : return address |
| 376 // -- esp[4] : key | |
| 377 // -- esp[8] : receiver | |
| 378 // ----------------------------------- | 374 // ----------------------------------- |
| 379 Label miss, index_ok; | 375 Label miss, index_ok; |
| 380 | 376 |
| 381 // Pop return address. | 377 // Pop return address. |
| 382 // Performing the load early is better in the common case. | 378 // Performing the load early is better in the common case. |
| 383 __ pop(eax); | 379 __ pop(ebx); |
| 384 | 380 |
| 385 __ mov(ebx, Operand(esp, 1 * kPointerSize)); | 381 __ test(edx, Immediate(kSmiTagMask)); |
| 386 __ test(ebx, Immediate(kSmiTagMask)); | |
| 387 __ j(zero, &miss); | 382 __ j(zero, &miss); |
| 388 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); | 383 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 389 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 384 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 390 __ test(ecx, Immediate(kIsNotStringMask)); | 385 __ test(ecx, Immediate(kIsNotStringMask)); |
| 391 __ j(not_zero, &miss); | 386 __ j(not_zero, &miss); |
| 392 | 387 |
| 393 // Check if key is a smi or a heap number. | 388 // Check if key is a smi or a heap number. |
| 394 __ mov(edx, Operand(esp, 0)); | 389 __ test(eax, Immediate(kSmiTagMask)); |
| 395 __ test(edx, Immediate(kSmiTagMask)); | |
| 396 __ j(zero, &index_ok); | 390 __ j(zero, &index_ok); |
| 397 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); | 391 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 398 __ cmp(ecx, Factory::heap_number_map()); | 392 __ cmp(ecx, Factory::heap_number_map()); |
| 399 __ j(not_equal, &miss); | 393 __ j(not_equal, &miss); |
| 400 | 394 |
| 401 __ bind(&index_ok); | 395 __ bind(&index_ok); |
| 402 // Duplicate receiver and key since they are expected on the stack after | 396 // Push receiver and key on the stack, and make a tail call. |
| 403 // the KeyedLoadIC call. | 397 __ push(edx); // receiver |
| 404 __ push(ebx); // receiver | 398 __ push(eax); // key |
| 405 __ push(edx); // key | 399 __ push(ebx); // return address |
| 406 __ push(eax); // return address | |
| 407 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); | 400 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); |
| 408 | 401 |
| 409 __ bind(&miss); | 402 __ bind(&miss); |
| 410 __ push(eax); | 403 __ push(ebx); |
| 411 GenerateMiss(masm); | 404 GenerateMiss(masm); |
| 412 } | 405 } |
| 413 | 406 |
| 414 | 407 |
| 415 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, | 408 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, |
| 416 ExternalArrayType array_type) { | 409 ExternalArrayType array_type) { |
| 417 // ----------- S t a t e ------------- | 410 // ----------- S t a t e ------------- |
| 411 // -- eax : key |
| 412 // -- edx : receiver |
| 418 // -- esp[0] : return address | 413 // -- esp[0] : return address |
| 419 // -- esp[4] : key | |
| 420 // -- esp[8] : receiver | |
| 421 // ----------------------------------- | 414 // ----------------------------------- |
| 422 Label slow, failed_allocation; | 415 Label slow, failed_allocation; |
| 423 | 416 |
| 424 // Load name and receiver. | |
| 425 __ mov(eax, Operand(esp, kPointerSize)); | |
| 426 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 427 | |
| 428 // Check that the object isn't a smi. | 417 // Check that the object isn't a smi. |
| 429 __ test(ecx, Immediate(kSmiTagMask)); | 418 __ test(edx, Immediate(kSmiTagMask)); |
| 430 __ j(zero, &slow, not_taken); | 419 __ j(zero, &slow, not_taken); |
| 431 | 420 |
| 432 // Check that the key is a smi. | 421 // Check that the key is a smi. |
| 433 __ test(eax, Immediate(kSmiTagMask)); | 422 __ test(eax, Immediate(kSmiTagMask)); |
| 434 __ j(not_zero, &slow, not_taken); | 423 __ j(not_zero, &slow, not_taken); |
| 435 | 424 |
| 436 // Get the map of the receiver. | 425 // Get the map of the receiver. |
| 437 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 426 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 438 // Check that the receiver does not require access checks. We need | 427 // Check that the receiver does not require access checks. We need |
| 439 // to check this explicitly since this generic stub does not perform | 428 // to check this explicitly since this generic stub does not perform |
| 440 // map checks. | 429 // map checks. |
| 441 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); | 430 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); |
| 442 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 431 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
| 443 __ j(not_zero, &slow, not_taken); | 432 __ j(not_zero, &slow, not_taken); |
| 444 | 433 |
| 445 // Get the instance type from the map of the receiver. | 434 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); |
| 446 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); | |
| 447 // Check that the object is a JS object. | |
| 448 __ cmp(edx, JS_OBJECT_TYPE); | |
| 449 __ j(not_equal, &slow, not_taken); | 435 __ j(not_equal, &slow, not_taken); |
| 450 | 436 |
| 451 // Check that the elements array is the appropriate type of | 437 // Check that the elements array is the appropriate type of |
| 452 // ExternalArray. | 438 // ExternalArray. |
| 453 // eax: index (as a smi) | 439 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
| 454 // ecx: JSObject | |
| 455 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); | |
| 456 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); | 440 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); |
| 457 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 441 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 458 Immediate(map)); | 442 Immediate(map)); |
| 459 __ j(not_equal, &slow, not_taken); | 443 __ j(not_equal, &slow, not_taken); |
| 460 | 444 |
| 445 // eax: key, known to be a smi. |
| 446 // edx: receiver, known to be a JSObject. |
| 447 // ebx: elements object, known to be an external array. |
| 461 // Check that the index is in range. | 448 // Check that the index is in range. |
| 462 __ sar(eax, kSmiTagSize); // Untag the index. | 449 __ mov(ecx, eax); |
| 463 __ cmp(eax, FieldOperand(ecx, ExternalArray::kLengthOffset)); | 450 __ SmiUntag(ecx); // Untag the index. |
| 451 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
| 464 // Unsigned comparison catches both negative and too-large values. | 452 // Unsigned comparison catches both negative and too-large values. |
| 465 __ j(above_equal, &slow); | 453 __ j(above_equal, &slow); |
| 466 | 454 |
| 467 // eax: untagged index | 455 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
| 468 // ecx: elements array | 456 // ebx: base pointer of external storage |
| 469 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | |
| 470 // ecx: base pointer of external storage | |
| 471 switch (array_type) { | 457 switch (array_type) { |
| 472 case kExternalByteArray: | 458 case kExternalByteArray: |
| 473 __ movsx_b(eax, Operand(ecx, eax, times_1, 0)); | 459 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); |
| 474 break; | 460 break; |
| 475 case kExternalUnsignedByteArray: | 461 case kExternalUnsignedByteArray: |
| 476 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | 462 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); |
| 477 break; | 463 break; |
| 478 case kExternalShortArray: | 464 case kExternalShortArray: |
| 479 __ movsx_w(eax, Operand(ecx, eax, times_2, 0)); | 465 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); |
| 480 break; | 466 break; |
| 481 case kExternalUnsignedShortArray: | 467 case kExternalUnsignedShortArray: |
| 482 __ movzx_w(eax, Operand(ecx, eax, times_2, 0)); | 468 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); |
| 483 break; | 469 break; |
| 484 case kExternalIntArray: | 470 case kExternalIntArray: |
| 485 case kExternalUnsignedIntArray: | 471 case kExternalUnsignedIntArray: |
| 486 __ mov(eax, Operand(ecx, eax, times_4, 0)); | 472 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); |
| 487 break; | 473 break; |
| 488 case kExternalFloatArray: | 474 case kExternalFloatArray: |
| 489 __ fld_s(Operand(ecx, eax, times_4, 0)); | 475 __ fld_s(Operand(ebx, ecx, times_4, 0)); |
| 490 break; | 476 break; |
| 491 default: | 477 default: |
| 492 UNREACHABLE(); | 478 UNREACHABLE(); |
| 493 break; | 479 break; |
| 494 } | 480 } |
| 495 | 481 |
| 496 // For integer array types: | 482 // For integer array types: |
| 497 // eax: value | 483 // ecx: value |
| 498 // For floating-point array type: | 484 // For floating-point array type: |
| 499 // FP(0): value | 485 // FP(0): value |
| 500 | 486 |
| 501 if (array_type == kExternalIntArray || | 487 if (array_type == kExternalIntArray || |
| 502 array_type == kExternalUnsignedIntArray) { | 488 array_type == kExternalUnsignedIntArray) { |
| 503 // For the Int and UnsignedInt array types, we need to see whether | 489 // For the Int and UnsignedInt array types, we need to see whether |
| 504 // the value can be represented in a Smi. If not, we need to convert | 490 // the value can be represented in a Smi. If not, we need to convert |
| 505 // it to a HeapNumber. | 491 // it to a HeapNumber. |
| 506 Label box_int; | 492 Label box_int; |
| 507 if (array_type == kExternalIntArray) { | 493 if (array_type == kExternalIntArray) { |
| 508 // See Smi::IsValid for why this works. | 494 __ cmp(ecx, 0xC0000000); |
| 509 __ mov(ebx, eax); | 495 __ j(sign, &box_int); |
| 510 __ add(Operand(ebx), Immediate(0x40000000)); | |
| 511 __ cmp(ebx, 0x80000000); | |
| 512 __ j(above_equal, &box_int); | |
| 513 } else { | 496 } else { |
| 514 ASSERT_EQ(array_type, kExternalUnsignedIntArray); | 497 ASSERT_EQ(array_type, kExternalUnsignedIntArray); |
| 515 // The test is different for unsigned int values. Since we need | 498 // The test is different for unsigned int values. Since we need |
| 516 // the Smi-encoded result to be treated as unsigned, we can't | 499 // the value to be in the range of a positive smi, we can't |
| 517 // handle either of the top two bits being set in the value. | 500 // handle either of the top two bits being set in the value. |
| 518 __ test(eax, Immediate(0xC0000000)); | 501 __ test(ecx, Immediate(0xC0000000)); |
| 519 __ j(not_zero, &box_int); | 502 __ j(not_zero, &box_int); |
| 520 } | 503 } |
| 521 | 504 |
| 522 __ shl(eax, kSmiTagSize); | 505 __ mov(eax, ecx); |
| 506 __ SmiTag(eax); |
| 523 __ ret(0); | 507 __ ret(0); |
| 524 | 508 |
| 525 __ bind(&box_int); | 509 __ bind(&box_int); |
| 526 | 510 |
| 527 // Allocate a HeapNumber for the int and perform int-to-double | 511 // Allocate a HeapNumber for the int and perform int-to-double |
| 528 // conversion. | 512 // conversion. |
| 529 if (array_type == kExternalIntArray) { | 513 if (array_type == kExternalIntArray) { |
| 530 __ push(eax); | 514 __ push(ecx); |
| 531 __ fild_s(Operand(esp, 0)); | 515 __ fild_s(Operand(esp, 0)); |
| 532 __ pop(eax); | 516 __ pop(ecx); |
| 533 } else { | 517 } else { |
| 534 ASSERT(array_type == kExternalUnsignedIntArray); | 518 ASSERT(array_type == kExternalUnsignedIntArray); |
| 535 // Need to zero-extend the value. | 519 // Need to zero-extend the value. |
| 536 // There's no fild variant for unsigned values, so zero-extend | 520 // There's no fild variant for unsigned values, so zero-extend |
| 537 // to a 64-bit int manually. | 521 // to a 64-bit int manually. |
| 538 __ push(Immediate(0)); | 522 __ push(Immediate(0)); |
| 539 __ push(eax); | 523 __ push(ecx); |
| 540 __ fild_d(Operand(esp, 0)); | 524 __ fild_d(Operand(esp, 0)); |
| 541 __ pop(eax); | 525 __ pop(ecx); |
| 542 __ pop(eax); | 526 __ pop(ecx); |
| 543 } | 527 } |
| 544 // FP(0): value | 528 // FP(0): value |
| 545 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); | 529 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
| 546 // Set the value. | 530 // Set the value. |
| 531 __ mov(eax, ecx); |
| 547 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 532 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 548 __ ret(0); | 533 __ ret(0); |
| 549 } else if (array_type == kExternalFloatArray) { | 534 } else if (array_type == kExternalFloatArray) { |
| 550 // For the floating-point array type, we need to always allocate a | 535 // For the floating-point array type, we need to always allocate a |
| 551 // HeapNumber. | 536 // HeapNumber. |
| 552 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); | 537 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
| 553 // Set the value. | 538 // Set the value. |
| 539 __ mov(eax, ecx); |
| 554 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 540 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 555 __ ret(0); | 541 __ ret(0); |
| 556 } else { | 542 } else { |
| 557 __ shl(eax, kSmiTagSize); | 543 __ mov(eax, ecx); |
| 544 __ SmiTag(eax); |
| 558 __ ret(0); | 545 __ ret(0); |
| 559 } | 546 } |
| 560 | 547 |
| 561 // If we fail allocation of the HeapNumber, we still have a value on | 548 // If we fail allocation of the HeapNumber, we still have a value on |
| 562 // top of the FPU stack. Remove it. | 549 // top of the FPU stack. Remove it. |
| 563 __ bind(&failed_allocation); | 550 __ bind(&failed_allocation); |
| 564 __ ffree(); | 551 __ ffree(); |
| 565 __ fincstp(); | 552 __ fincstp(); |
| 566 // Fall through to slow case. | 553 // Fall through to slow case. |
| 567 | 554 |
| 568 // Slow case: Load name and receiver from stack and jump to runtime. | 555 // Slow case: Load key and receiver from stack and jump to runtime. |
| 569 __ bind(&slow); | 556 __ bind(&slow); |
| 570 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); | 557 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); |
| 571 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 558 GenerateRuntimeGetProperty(masm); |
| 559 } |
| 560 |
| 561 |
| 562 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 563 // ----------- S t a t e ------------- |
| 564 // -- eax : key |
| 565 // -- edx : receiver |
| 566 // -- esp[0] : return address |
| 567 // ----------------------------------- |
| 568 Label slow; |
| 569 |
| 570 // Check that the receiver isn't a smi. |
| 571 __ test(edx, Immediate(kSmiTagMask)); |
| 572 __ j(zero, &slow, not_taken); |
| 573 |
| 574 // Check that the key is a smi. |
| 575 __ test(eax, Immediate(kSmiTagMask)); |
| 576 __ j(not_zero, &slow, not_taken); |
| 577 |
| 578 // Get the map of the receiver. |
| 579 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 580 |
| 581 // Check that it has indexed interceptor and access checks |
| 582 // are not enabled for this object. |
| 583 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); |
| 584 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); |
| 585 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); |
| 586 __ j(not_zero, &slow, not_taken); |
| 587 |
| 588 // Everything is fine, call runtime. |
| 589 __ pop(ecx); |
| 590 __ push(edx); // receiver |
| 591 __ push(eax); // key |
| 592 __ push(ecx); // return address |
| 593 |
| 594 // Perform tail call to the entry. |
| 595 __ TailCallRuntime(ExternalReference( |
| 596 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
| 597 |
| 598 __ bind(&slow); |
| 599 GenerateMiss(masm); |
| 572 } | 600 } |
| 573 | 601 |
| 574 | 602 |
| 575 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 603 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
| 576 // ----------- S t a t e ------------- | 604 // ----------- S t a t e ------------- |
| 577 // -- eax : value | 605 // -- eax : value |
| 578 // -- esp[0] : return address | 606 // -- esp[0] : return address |
| 579 // -- esp[4] : key | 607 // -- esp[4] : key |
| 580 // -- esp[8] : receiver | 608 // -- esp[8] : receiver |
| 581 // ----------------------------------- | 609 // ----------------------------------- |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 __ mov(edx, Operand(ebx)); | 648 __ mov(edx, Operand(ebx)); |
| 621 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison | 649 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison |
| 622 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); | 650 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); |
| 623 // eax: value | 651 // eax: value |
| 624 // ecx: FixedArray | 652 // ecx: FixedArray |
| 625 // ebx: index (as a smi) | 653 // ebx: index (as a smi) |
| 626 __ j(below, &fast, taken); | 654 __ j(below, &fast, taken); |
| 627 | 655 |
| 628 // Slow case: call runtime. | 656 // Slow case: call runtime. |
| 629 __ bind(&slow); | 657 __ bind(&slow); |
| 630 Generate(masm, ExternalReference(Runtime::kSetProperty)); | 658 GenerateRuntimeSetProperty(masm); |
| 631 | 659 |
| 632 // Check whether the elements is a pixel array. | 660 // Check whether the elements is a pixel array. |
| 633 // eax: value | 661 // eax: value |
| 634 // ecx: elements array | 662 // ecx: elements array |
| 635 // ebx: index (as a smi) | 663 // ebx: index (as a smi) |
| 636 __ bind(&check_pixel_array); | 664 __ bind(&check_pixel_array); |
| 637 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 665 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 638 Immediate(Factory::pixel_array_map())); | 666 Immediate(Factory::pixel_array_map())); |
| 639 __ j(not_equal, &slow); | 667 __ j(not_equal, &slow); |
| 640 // Check that the value is a smi. If a conversion is needed call into the | 668 // Check that the value is a smi. If a conversion is needed call into the |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 default: | 921 default: |
| 894 UNREACHABLE(); | 922 UNREACHABLE(); |
| 895 break; | 923 break; |
| 896 } | 924 } |
| 897 __ mov(eax, edx); // Return the original value. | 925 __ mov(eax, edx); // Return the original value. |
| 898 __ ret(0); | 926 __ ret(0); |
| 899 } | 927 } |
| 900 | 928 |
| 901 // Slow case: call runtime. | 929 // Slow case: call runtime. |
| 902 __ bind(&slow); | 930 __ bind(&slow); |
| 903 Generate(masm, ExternalReference(Runtime::kSetProperty)); | 931 GenerateRuntimeSetProperty(masm); |
| 904 } | 932 } |
| 905 | 933 |
| 906 | 934 |
| 907 // Defined in ic.cc. | 935 // Defined in ic.cc. |
| 908 Object* CallIC_Miss(Arguments args); | 936 Object* CallIC_Miss(Arguments args); |
| 909 | 937 |
| 910 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 938 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 911 // ----------- S t a t e ------------- | 939 // ----------- S t a t e ------------- |
| 912 // -- ecx : name | 940 // -- ecx : name |
| 913 // -- esp[0] : return address | 941 // -- esp[0] : return address |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 // -- ecx : name | 1004 // -- ecx : name |
| 977 // -- edx : receiver | 1005 // -- edx : receiver |
| 978 // -- esp[0] : return address | 1006 // -- esp[0] : return address |
| 979 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1007 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 980 // -- ... | 1008 // -- ... |
| 981 // -- esp[(argc + 1) * 4] : receiver | 1009 // -- esp[(argc + 1) * 4] : receiver |
| 982 // ----------------------------------- | 1010 // ----------------------------------- |
| 983 | 1011 |
| 984 // Search dictionary - put result in register edi. | 1012 // Search dictionary - put result in register edi. |
| 985 __ mov(edi, edx); | 1013 __ mov(edi, edx); |
| 986 GenerateDictionaryLoad(masm, miss, eax, edi, ebx, ecx, CHECK_DICTIONARY); | 1014 GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY); |
| 987 | 1015 |
| 988 // Check that the result is not a smi. | 1016 // Check that the result is not a smi. |
| 989 __ test(edi, Immediate(kSmiTagMask)); | 1017 __ test(edi, Immediate(kSmiTagMask)); |
| 990 __ j(zero, miss, not_taken); | 1018 __ j(zero, miss, not_taken); |
| 991 | 1019 |
| 992 // Check that the value is a JavaScript function, fetching its map into eax. | 1020 // Check that the value is a JavaScript function, fetching its map into eax. |
| 993 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); | 1021 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); |
| 994 __ j(not_equal, miss, not_taken); | 1022 __ j(not_equal, miss, not_taken); |
| 995 | 1023 |
| 996 // Patch the receiver on stack with the global proxy if necessary. | 1024 // Patch the receiver on stack with the global proxy if necessary. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 __ bind(&invoke); | 1148 __ bind(&invoke); |
| 1121 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 1149 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| 1122 } | 1150 } |
| 1123 | 1151 |
| 1124 | 1152 |
| 1125 // Defined in ic.cc. | 1153 // Defined in ic.cc. |
| 1126 Object* LoadIC_Miss(Arguments args); | 1154 Object* LoadIC_Miss(Arguments args); |
| 1127 | 1155 |
| 1128 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1156 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1129 // ----------- S t a t e ------------- | 1157 // ----------- S t a t e ------------- |
| 1158 // -- eax : receiver |
| 1130 // -- ecx : name | 1159 // -- ecx : name |
| 1131 // -- esp[0] : return address | 1160 // -- esp[0] : return address |
| 1132 // -- esp[4] : receiver | |
| 1133 // ----------------------------------- | 1161 // ----------------------------------- |
| 1134 | 1162 |
| 1135 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1136 | |
| 1137 // Probe the stub cache. | 1163 // Probe the stub cache. |
| 1138 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, | 1164 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, |
| 1139 NOT_IN_LOOP, | 1165 NOT_IN_LOOP, |
| 1140 MONOMORPHIC); | 1166 MONOMORPHIC); |
| 1141 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); | 1167 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); |
| 1142 | 1168 |
| 1143 // Cache miss: Jump to runtime. | 1169 // Cache miss: Jump to runtime. |
| 1144 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | 1170 GenerateMiss(masm); |
| 1145 } | 1171 } |
| 1146 | 1172 |
| 1147 | 1173 |
| 1148 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 1174 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 1149 // ----------- S t a t e ------------- | 1175 // ----------- S t a t e ------------- |
| 1176 // -- eax : receiver |
| 1150 // -- ecx : name | 1177 // -- ecx : name |
| 1151 // -- esp[0] : return address | 1178 // -- esp[0] : return address |
| 1152 // -- esp[4] : receiver | |
| 1153 // ----------------------------------- | 1179 // ----------------------------------- |
| 1154 Label miss, probe, global; | 1180 Label miss, probe, global; |
| 1155 | 1181 |
| 1156 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1157 | |
| 1158 // Check that the receiver isn't a smi. | 1182 // Check that the receiver isn't a smi. |
| 1159 __ test(eax, Immediate(kSmiTagMask)); | 1183 __ test(eax, Immediate(kSmiTagMask)); |
| 1160 __ j(zero, &miss, not_taken); | 1184 __ j(zero, &miss, not_taken); |
| 1161 | 1185 |
| 1162 // Check that the receiver is a valid JS object. | 1186 // Check that the receiver is a valid JS object. |
| 1163 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 1187 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 1164 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 1188 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 1165 __ cmp(edx, FIRST_JS_OBJECT_TYPE); | 1189 __ cmp(edx, FIRST_JS_OBJECT_TYPE); |
| 1166 __ j(less, &miss, not_taken); | 1190 __ j(less, &miss, not_taken); |
| 1167 | 1191 |
| 1168 // If this assert fails, we have to check upper bound too. | 1192 // If this assert fails, we have to check upper bound too. |
| 1169 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1193 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 1170 | 1194 |
| 1171 // Check for access to global object (unlikely). | 1195 // Check for access to global object (unlikely). |
| 1172 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); | 1196 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); |
| 1173 __ j(equal, &global, not_taken); | 1197 __ j(equal, &global, not_taken); |
| 1174 | 1198 |
| 1175 // Check for non-global object that requires access check. | 1199 // Check for non-global object that requires access check. |
| 1176 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 1200 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
| 1177 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 1201 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
| 1178 __ j(not_zero, &miss, not_taken); | 1202 __ j(not_zero, &miss, not_taken); |
| 1179 | 1203 |
| 1180 // Search the dictionary placing the result in eax. | 1204 // Search the dictionary placing the result in eax. |
| 1181 __ bind(&probe); | 1205 __ bind(&probe); |
| 1182 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY); | 1206 GenerateDictionaryLoad(masm, |
| 1207 &miss, |
| 1208 eax, |
| 1209 ecx, |
| 1210 edx, |
| 1211 edi, |
| 1212 ebx, |
| 1213 CHECK_DICTIONARY); |
| 1214 __ mov(eax, edi); |
| 1183 __ ret(0); | 1215 __ ret(0); |
| 1184 | 1216 |
| 1185 // Global object access: Check access rights. | 1217 // Global object access: Check access rights. |
| 1186 __ bind(&global); | 1218 __ bind(&global); |
| 1187 __ CheckAccessGlobalProxy(eax, edx, &miss); | 1219 __ CheckAccessGlobalProxy(eax, edx, &miss); |
| 1188 __ jmp(&probe); | 1220 __ jmp(&probe); |
| 1189 | 1221 |
| 1190 // Cache miss: Restore receiver from stack and jump to runtime. | 1222 // Cache miss: Restore receiver from stack and jump to runtime. |
| 1191 __ bind(&miss); | 1223 __ bind(&miss); |
| 1192 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 1224 GenerateMiss(masm); |
| 1193 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 1194 } | 1225 } |
| 1195 | 1226 |
| 1196 | 1227 |
| 1197 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 1228 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1198 // ----------- S t a t e ------------- | 1229 // ----------- S t a t e ------------- |
| 1230 // -- eax : receiver |
| 1199 // -- ecx : name | 1231 // -- ecx : name |
| 1200 // -- esp[0] : return address | 1232 // -- esp[0] : return address |
| 1201 // -- esp[4] : receiver | |
| 1202 // ----------------------------------- | 1233 // ----------------------------------- |
| 1203 | 1234 |
| 1204 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 1205 } | |
| 1206 | |
| 1207 | |
| 1208 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) { | |
| 1209 // ----------- S t a t e ------------- | |
| 1210 // -- ecx : name | |
| 1211 // -- esp[0] : return address | |
| 1212 // -- esp[4] : receiver | |
| 1213 // ----------------------------------- | |
| 1214 | |
| 1215 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1216 __ pop(ebx); | 1235 __ pop(ebx); |
| 1217 __ push(eax); // receiver | 1236 __ push(eax); // receiver |
| 1218 __ push(ecx); // name | 1237 __ push(ecx); // name |
| 1219 __ push(ebx); // return address | 1238 __ push(ebx); // return address |
| 1220 | 1239 |
| 1221 // Perform tail call to the entry. | 1240 // Perform tail call to the entry. |
| 1222 __ TailCallRuntime(f, 2, 1); | 1241 __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1); |
| 1223 } | 1242 } |
| 1224 | 1243 |
| 1225 | 1244 |
| 1226 // One byte opcode for test eax,0xXXXXXXXX. | 1245 // One byte opcode for test eax,0xXXXXXXXX. |
| 1227 static const byte kTestEaxByte = 0xA9; | 1246 static const byte kTestEaxByte = 0xA9; |
| 1228 | 1247 |
| 1229 | 1248 |
| 1230 void LoadIC::ClearInlinedVersion(Address address) { | 1249 void LoadIC::ClearInlinedVersion(Address address) { |
| 1231 // Reset the map check of the inlined inobject property load (if | 1250 // Reset the map check of the inlined inobject property load (if |
| 1232 // present) to guarantee failure by holding an invalid map (the null | 1251 // present) to guarantee failure by holding an invalid map (the null |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 return PatchInlinedMapCheck(address, map); | 1335 return PatchInlinedMapCheck(address, map); |
| 1317 } | 1336 } |
| 1318 | 1337 |
| 1319 | 1338 |
| 1320 // Defined in ic.cc. | 1339 // Defined in ic.cc. |
| 1321 Object* KeyedLoadIC_Miss(Arguments args); | 1340 Object* KeyedLoadIC_Miss(Arguments args); |
| 1322 | 1341 |
| 1323 | 1342 |
| 1324 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1343 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1325 // ----------- S t a t e ------------- | 1344 // ----------- S t a t e ------------- |
| 1345 // -- eax : key |
| 1346 // -- edx : receiver |
| 1326 // -- esp[0] : return address | 1347 // -- esp[0] : return address |
| 1327 // -- esp[4] : name | |
| 1328 // -- esp[8] : receiver | |
| 1329 // ----------------------------------- | 1348 // ----------------------------------- |
| 1330 | 1349 |
| 1331 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); | |
| 1332 } | |
| 1333 | |
| 1334 | |
| 1335 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) { | |
| 1336 // ----------- S t a t e ------------- | |
| 1337 // -- esp[0] : return address | |
| 1338 // -- esp[4] : name | |
| 1339 // -- esp[8] : receiver | |
| 1340 // ----------------------------------- | |
| 1341 | |
| 1342 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1343 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1344 __ pop(ebx); | 1350 __ pop(ebx); |
| 1345 __ push(ecx); // receiver | 1351 __ push(edx); // receiver |
| 1346 __ push(eax); // name | 1352 __ push(eax); // name |
| 1347 __ push(ebx); // return address | 1353 __ push(ebx); // return address |
| 1348 | 1354 |
| 1349 // Perform tail call to the entry. | 1355 // Perform tail call to the entry. |
| 1350 __ TailCallRuntime(f, 2, 1); | 1356 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1); |
| 1351 } | 1357 } |
| 1352 | 1358 |
| 1353 | 1359 |
| 1360 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1361 // ----------- S t a t e ------------- |
| 1362 // -- eax : key |
| 1363 // -- edx : receiver |
| 1364 // -- esp[0] : return address |
| 1365 // ----------------------------------- |
| 1366 |
| 1367 __ pop(ebx); |
| 1368 __ push(edx); // receiver |
| 1369 __ push(eax); // name |
| 1370 __ push(ebx); // return address |
| 1371 |
| 1372 // Perform tail call to the entry. |
| 1373 __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1); |
| 1374 } |
| 1375 |
| 1376 |
| 1354 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1377 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1355 // ----------- S t a t e ------------- | 1378 // ----------- S t a t e ------------- |
| 1356 // -- eax : value | 1379 // -- eax : value |
| 1357 // -- ecx : name | 1380 // -- ecx : name |
| 1358 // -- edx : receiver | 1381 // -- edx : receiver |
| 1359 // -- esp[0] : return address | 1382 // -- esp[0] : return address |
| 1360 // ----------------------------------- | 1383 // ----------------------------------- |
| 1361 | 1384 |
| 1362 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1385 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1363 NOT_IN_LOOP, | 1386 NOT_IN_LOOP, |
| 1364 MONOMORPHIC); | 1387 MONOMORPHIC); |
| 1365 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); | 1388 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); |
| 1366 | 1389 |
| 1367 // Cache miss: Jump to runtime. | 1390 // Cache miss: Jump to runtime. |
| 1368 GenerateMiss(masm); | 1391 GenerateMiss(masm); |
| 1369 } | 1392 } |
| 1370 | 1393 |
| 1371 | 1394 |
| 1372 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { | |
| 1373 // ----------- S t a t e ------------- | |
| 1374 // -- eax : value | |
| 1375 // -- ecx : transition map | |
| 1376 // -- edx : receiver | |
| 1377 // -- esp[0] : return address | |
| 1378 // ----------------------------------- | |
| 1379 | |
| 1380 __ pop(ebx); | |
| 1381 __ push(edx); // receiver | |
| 1382 __ push(ecx); // transition map | |
| 1383 __ push(eax); // value | |
| 1384 __ push(ebx); // return address | |
| 1385 | |
| 1386 // Perform tail call to the entry. | |
| 1387 __ TailCallRuntime( | |
| 1388 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 1389 } | |
| 1390 | |
| 1391 | |
| 1392 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1395 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1393 // ----------- S t a t e ------------- | 1396 // ----------- S t a t e ------------- |
| 1394 // -- eax : value | 1397 // -- eax : value |
| 1395 // -- ecx : name | 1398 // -- ecx : name |
| 1396 // -- edx : receiver | 1399 // -- edx : receiver |
| 1397 // -- esp[0] : return address | 1400 // -- esp[0] : return address |
| 1398 // ----------------------------------- | 1401 // ----------------------------------- |
| 1399 | 1402 |
| 1400 __ pop(ebx); | 1403 __ pop(ebx); |
| 1401 __ push(edx); | 1404 __ push(edx); |
| 1402 __ push(ecx); | 1405 __ push(ecx); |
| 1403 __ push(eax); | 1406 __ push(eax); |
| 1404 __ push(ebx); | 1407 __ push(ebx); |
| 1405 | 1408 |
| 1406 // Perform tail call to the entry. | 1409 // Perform tail call to the entry. |
| 1407 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); | 1410 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); |
| 1408 } | 1411 } |
| 1409 | 1412 |
| 1410 | 1413 |
| 1414 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1415 // ----------- S t a t e ------------- |
| 1416 // -- eax : value |
| 1417 // -- ecx : name |
| 1418 // -- edx : receiver |
| 1419 // -- esp[0] : return address |
| 1420 // ----------------------------------- |
| 1421 // |
| 1422 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1423 // (currently anything except for external and pixel arrays which means |
| 1424 // anything with elements of FixedArray type.), but currently is restricted |
| 1425 // to JSArray. |
| 1426 // Value must be a number, but only smis are accepted as the most common case. |
| 1427 |
| 1428 Label miss; |
| 1429 |
| 1430 Register receiver = edx; |
| 1431 Register value = eax; |
| 1432 Register scratch = ebx; |
| 1433 |
| 1434 // Check that the receiver isn't a smi. |
| 1435 __ test(receiver, Immediate(kSmiTagMask)); |
| 1436 __ j(zero, &miss, not_taken); |
| 1437 |
| 1438 // Check that the object is a JS array. |
| 1439 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 1440 __ j(not_equal, &miss, not_taken); |
| 1441 |
| 1442 // Check that elements are FixedArray. |
| 1443 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
| 1444 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
| 1445 __ j(not_equal, &miss, not_taken); |
| 1446 |
| 1447 // Check that value is a smi. |
| 1448 __ test(value, Immediate(kSmiTagMask)); |
| 1449 __ j(not_zero, &miss, not_taken); |
| 1450 |
| 1451 // Prepare tail call to StoreIC_ArrayLength. |
| 1452 __ pop(scratch); |
| 1453 __ push(receiver); |
| 1454 __ push(value); |
| 1455 __ push(scratch); // return address |
| 1456 |
| 1457 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ArrayLength)), 2, 1); |
| 1458 |
| 1459 __ bind(&miss); |
| 1460 |
| 1461 GenerateMiss(masm); |
| 1462 } |
| 1463 |
| 1464 |
| 1411 // Defined in ic.cc. | 1465 // Defined in ic.cc. |
| 1412 Object* KeyedStoreIC_Miss(Arguments args); | 1466 Object* KeyedStoreIC_Miss(Arguments args); |
| 1413 | 1467 |
| 1414 void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) { | 1468 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1415 // ----------- S t a t e ------------- | 1469 // ----------- S t a t e ------------- |
| 1416 // -- eax : value | 1470 // -- eax : value |
| 1417 // -- esp[0] : return address | 1471 // -- esp[0] : return address |
| 1418 // -- esp[4] : key | 1472 // -- esp[4] : key |
| 1419 // -- esp[8] : receiver | 1473 // -- esp[8] : receiver |
| 1420 // ----------------------------------- | 1474 // ----------------------------------- |
| 1421 | 1475 |
| 1422 __ pop(ecx); | 1476 __ pop(ecx); |
| 1423 __ push(Operand(esp, 1 * kPointerSize)); | 1477 __ push(Operand(esp, 1 * kPointerSize)); |
| 1424 __ push(Operand(esp, 1 * kPointerSize)); | 1478 __ push(Operand(esp, 1 * kPointerSize)); |
| 1425 __ push(eax); | 1479 __ push(eax); |
| 1426 __ push(ecx); | 1480 __ push(ecx); |
| 1427 | 1481 |
| 1428 // Do tail-call to runtime routine. | 1482 // Do tail-call to runtime routine. |
| 1429 __ TailCallRuntime(f, 3, 1); | 1483 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); |
| 1430 } | 1484 } |
| 1431 | 1485 |
| 1432 | 1486 |
| 1433 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) { | 1487 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1434 // ----------- S t a t e ------------- | 1488 // ----------- S t a t e ------------- |
| 1435 // -- eax : value | 1489 // -- eax : value |
| 1436 // -- ecx : transition map | |
| 1437 // -- esp[0] : return address | 1490 // -- esp[0] : return address |
| 1438 // -- esp[4] : key | 1491 // -- esp[4] : key |
| 1439 // -- esp[8] : receiver | 1492 // -- esp[8] : receiver |
| 1440 // ----------------------------------- | 1493 // ----------------------------------- |
| 1441 | 1494 |
| 1442 __ pop(ebx); | 1495 __ pop(ecx); |
| 1443 __ push(Operand(esp, 1 * kPointerSize)); | 1496 __ push(Operand(esp, 1 * kPointerSize)); |
| 1497 __ push(Operand(esp, 1 * kPointerSize)); |
| 1498 __ push(eax); |
| 1444 __ push(ecx); | 1499 __ push(ecx); |
| 1445 __ push(eax); | |
| 1446 __ push(ebx); | |
| 1447 | 1500 |
| 1448 // Do tail-call to runtime routine. | 1501 // Do tail-call to runtime routine. |
| 1449 __ TailCallRuntime( | 1502 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1); |
| 1450 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 1451 } | 1503 } |
| 1452 | 1504 |
| 1453 #undef __ | 1505 #undef __ |
| 1454 | 1506 |
| 1455 | 1507 |
| 1456 } } // namespace v8::internal | 1508 } } // namespace v8::internal |
| OLD | NEW |