| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 // | 52 // |
| 53 // t0 - used to hold the property dictionary. | 53 // t0 - used to hold the property dictionary. |
| 54 // | 54 // |
| 55 // t1 - initially the receiver | 55 // t1 - initially the receiver |
| 56 // - used for the index into the property dictionary | 56 // - used for the index into the property dictionary |
| 57 // - holds the result on exit. | 57 // - holds the result on exit. |
| 58 // | 58 // |
| 59 // r3 - used as temporary and to hold the capacity of the property | 59 // r3 - used as temporary and to hold the capacity of the property |
| 60 // dictionary. | 60 // dictionary. |
| 61 // | 61 // |
| 62 // r2 - holds the name of the property and is unchanges. | 62 // r2 - holds the name of the property and is unchanged. |
| 63 | 63 |
| 64 Label done; | 64 Label done; |
| 65 | 65 |
| 66 // Check for the absence of an interceptor. | 66 // Check for the absence of an interceptor. |
| 67 // Load the map into t0. | 67 // Load the map into t0. |
| 68 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); | 68 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); |
| 69 // Test the has_named_interceptor bit in the map. | 69 // Test the has_named_interceptor bit in the map. |
| 70 __ ldr(r3, FieldMemOperand(t0, Map::kInstanceAttributesOffset)); | 70 __ ldr(r3, FieldMemOperand(t0, Map::kInstanceAttributesOffset)); |
| 71 __ tst(r3, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); | 71 __ tst(r3, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); |
| 72 // Jump to miss if the interceptor bit is set. | 72 // Jump to miss if the interceptor bit is set. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 164 void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
| 165 // ----------- S t a t e ------------- | 165 // ----------- S t a t e ------------- |
| 166 // -- r2 : name | 166 // -- r2 : name |
| 167 // -- lr : return address | 167 // -- lr : return address |
| 168 // -- [sp] : receiver | 168 // -- [sp] : receiver |
| 169 // ----------------------------------- | 169 // ----------------------------------- |
| 170 Label miss; | 170 Label miss; |
| 171 | 171 |
| 172 __ ldr(r0, MemOperand(sp, 0)); | 172 __ ldr(r0, MemOperand(sp, 0)); |
| 173 | 173 |
| 174 StubCompiler::GenerateLoadStringLength2(masm, r0, r1, r3, &miss); | 174 StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss); |
| 175 // Cache miss: Jump to runtime. | 175 // Cache miss: Jump to runtime. |
| 176 __ bind(&miss); | 176 __ bind(&miss); |
| 177 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 177 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { | 181 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { |
| 182 // ----------- S t a t e ------------- | 182 // ----------- S t a t e ------------- |
| 183 // -- r2 : name | 183 // -- r2 : name |
| 184 // -- lr : return address | 184 // -- lr : return address |
| 185 // -- [sp] : receiver | 185 // -- [sp] : receiver |
| 186 // ----------------------------------- | 186 // ----------------------------------- |
| 187 Label miss; | 187 Label miss; |
| 188 | 188 |
| 189 // Load receiver. | 189 // Load receiver. |
| 190 __ ldr(r0, MemOperand(sp, 0)); | 190 __ ldr(r0, MemOperand(sp, 0)); |
| 191 | 191 |
| 192 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); | 192 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); |
| 193 __ bind(&miss); | 193 __ bind(&miss); |
| 194 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 194 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 195 } | 195 } |
| 196 | 196 |
| 197 | 197 |
| 198 // Defined in ic.cc. | 198 // Defined in ic.cc. |
| 199 Object* CallIC_Miss(Arguments args); | 199 Object* CallIC_Miss(Arguments args); |
| 200 | 200 |
| 201 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 201 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 202 // ----------- S t a t e ------------- | 202 // ----------- S t a t e ------------- |
| 203 // -- lr: return address | 203 // -- r2 : name |
| 204 // -- lr : return address |
| 204 // ----------------------------------- | 205 // ----------------------------------- |
| 205 Label number, non_number, non_string, boolean, probe, miss; | 206 Label number, non_number, non_string, boolean, probe, miss; |
| 206 | 207 |
| 207 // Get the receiver of the function from the stack into r1. | 208 // Get the receiver of the function from the stack into r1. |
| 208 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 209 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 209 // Get the name of the function from the stack; 1 ~ receiver. | |
| 210 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize)); | |
| 211 | 210 |
| 212 // Probe the stub cache. | 211 // Probe the stub cache. |
| 213 Code::Flags flags = | 212 Code::Flags flags = |
| 214 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); | 213 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); |
| 215 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); | 214 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); |
| 216 | 215 |
| 217 // If the stub cache probing failed, the receiver might be a value. | 216 // If the stub cache probing failed, the receiver might be a value. |
| 218 // For value objects, we use the map of the prototype objects for | 217 // For value objects, we use the map of the prototype objects for |
| 219 // the corresponding JSValue for the cache and that is what we need | 218 // the corresponding JSValue for the cache and that is what we need |
| 220 // to probe. | 219 // to probe. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 // Check that the value isn't a smi. | 268 // Check that the value isn't a smi. |
| 270 __ tst(r1, Operand(kSmiTagMask)); | 269 __ tst(r1, Operand(kSmiTagMask)); |
| 271 __ b(eq, miss); | 270 __ b(eq, miss); |
| 272 | 271 |
| 273 // Check that the value is a JSFunction. | 272 // Check that the value is a JSFunction. |
| 274 __ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE); | 273 __ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE); |
| 275 __ b(ne, miss); | 274 __ b(ne, miss); |
| 276 | 275 |
| 277 // Patch the receiver with the global proxy if necessary. | 276 // Patch the receiver with the global proxy if necessary. |
| 278 if (is_global_object) { | 277 if (is_global_object) { |
| 279 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); | 278 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 280 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); | 279 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
| 281 __ str(r2, MemOperand(sp, argc * kPointerSize)); | 280 __ str(r0, MemOperand(sp, argc * kPointerSize)); |
| 282 } | 281 } |
| 283 | 282 |
| 284 // Invoke the function. | 283 // Invoke the function. |
| 285 ParameterCount actual(argc); | 284 ParameterCount actual(argc); |
| 286 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | 285 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
| 287 } | 286 } |
| 288 | 287 |
| 289 | 288 |
| 290 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 289 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 291 // ----------- S t a t e ------------- | 290 // ----------- S t a t e ------------- |
| 292 // -- lr: return address | 291 // -- r2 : name |
| 292 // -- lr : return address |
| 293 // ----------------------------------- | 293 // ----------------------------------- |
| 294 Label miss, global_object, non_global_object; | 294 Label miss, global_object, non_global_object; |
| 295 | 295 |
| 296 // Get the receiver of the function from the stack into r1. | 296 // Get the receiver of the function from the stack into r1. |
| 297 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 297 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 298 // Get the name of the function from the stack; 1 ~ receiver. | |
| 299 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize)); | |
| 300 | 298 |
| 301 // Check that the receiver isn't a smi. | 299 // Check that the receiver isn't a smi. |
| 302 __ tst(r1, Operand(kSmiTagMask)); | 300 __ tst(r1, Operand(kSmiTagMask)); |
| 303 __ b(eq, &miss); | 301 __ b(eq, &miss); |
| 304 | 302 |
| 305 // Check that the receiver is a valid JS object. Put the map in r3. | 303 // Check that the receiver is a valid JS object. Put the map in r3. |
| 306 __ CompareObjectType(r1, r3, r0, FIRST_JS_OBJECT_TYPE); | 304 __ CompareObjectType(r1, r3, r0, FIRST_JS_OBJECT_TYPE); |
| 307 __ b(lt, &miss); | 305 __ b(lt, &miss); |
| 308 | 306 |
| 309 // If this assert fails, we have to check upper bound too. | 307 // If this assert fails, we have to check upper bound too. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 __ b(&invoke); | 340 __ b(&invoke); |
| 343 | 341 |
| 344 // Cache miss: Jump to runtime. | 342 // Cache miss: Jump to runtime. |
| 345 __ bind(&miss); | 343 __ bind(&miss); |
| 346 GenerateMiss(masm, argc); | 344 GenerateMiss(masm, argc); |
| 347 } | 345 } |
| 348 | 346 |
| 349 | 347 |
| 350 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 348 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 351 // ----------- S t a t e ------------- | 349 // ----------- S t a t e ------------- |
| 352 // -- lr: return address | 350 // -- r2 : name |
| 351 // -- lr : return address |
| 353 // ----------------------------------- | 352 // ----------------------------------- |
| 354 | 353 |
| 355 // Get the receiver of the function from the stack. | 354 // Get the receiver of the function from the stack. |
| 356 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); | 355 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); |
| 357 // Get the name of the function to call from the stack. | |
| 358 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize)); | |
| 359 | 356 |
| 360 __ EnterInternalFrame(); | 357 __ EnterInternalFrame(); |
| 361 | 358 |
| 362 // Push the receiver and the name of the function. | 359 // Push the receiver and the name of the function. |
| 363 __ stm(db_w, sp, r1.bit() | r2.bit()); | 360 __ stm(db_w, sp, r2.bit() | r3.bit()); |
| 364 | 361 |
| 365 // Call the entry. | 362 // Call the entry. |
| 366 __ mov(r0, Operand(2)); | 363 __ mov(r0, Operand(2)); |
| 367 __ mov(r1, Operand(ExternalReference(IC_Utility(kCallIC_Miss)))); | 364 __ mov(r1, Operand(ExternalReference(IC_Utility(kCallIC_Miss)))); |
| 368 | 365 |
| 369 CEntryStub stub(1); | 366 CEntryStub stub(1); |
| 370 __ CallStub(&stub); | 367 __ CallStub(&stub); |
| 371 | 368 |
| 372 // Move result to r1 and leave the internal frame. | 369 // Move result to r1 and leave the internal frame. |
| 373 __ mov(r1, Operand(r0)); | 370 __ mov(r1, Operand(r0)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 // ----------------------------------- | 403 // ----------------------------------- |
| 407 | 404 |
| 408 __ ldr(r0, MemOperand(sp, 0)); | 405 __ ldr(r0, MemOperand(sp, 0)); |
| 409 // Probe the stub cache. | 406 // Probe the stub cache. |
| 410 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, | 407 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, |
| 411 NOT_IN_LOOP, | 408 NOT_IN_LOOP, |
| 412 MONOMORPHIC); | 409 MONOMORPHIC); |
| 413 StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg); | 410 StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg); |
| 414 | 411 |
| 415 // Cache miss: Jump to runtime. | 412 // Cache miss: Jump to runtime. |
| 416 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | 413 GenerateMiss(masm); |
| 417 } | 414 } |
| 418 | 415 |
| 419 | 416 |
| 420 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 417 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 421 // ----------- S t a t e ------------- | 418 // ----------- S t a t e ------------- |
| 422 // -- r2 : name | 419 // -- r2 : name |
| 423 // -- lr : return address | 420 // -- lr : return address |
| 424 // -- [sp] : receiver | 421 // -- [sp] : receiver |
| 425 // ----------------------------------- | 422 // ----------------------------------- |
| 426 Label miss, probe, global; | 423 Label miss, probe, global; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 449 GenerateDictionaryLoad(masm, &miss, r1, r0); | 446 GenerateDictionaryLoad(masm, &miss, r1, r0); |
| 450 __ Ret(); | 447 __ Ret(); |
| 451 | 448 |
| 452 // Global object access: Check access rights. | 449 // Global object access: Check access rights. |
| 453 __ bind(&global); | 450 __ bind(&global); |
| 454 __ CheckAccessGlobalProxy(r0, r1, &miss); | 451 __ CheckAccessGlobalProxy(r0, r1, &miss); |
| 455 __ b(&probe); | 452 __ b(&probe); |
| 456 | 453 |
| 457 // Cache miss: Restore receiver from stack and jump to runtime. | 454 // Cache miss: Restore receiver from stack and jump to runtime. |
| 458 __ bind(&miss); | 455 __ bind(&miss); |
| 459 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | 456 GenerateMiss(masm); |
| 460 } | 457 } |
| 461 | 458 |
| 462 | 459 |
| 463 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 460 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 464 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 465 } | |
| 466 | |
| 467 | |
| 468 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) { | |
| 469 // ----------- S t a t e ------------- | 461 // ----------- S t a t e ------------- |
| 470 // -- r2 : name | 462 // -- r2 : name |
| 471 // -- lr : return address | 463 // -- lr : return address |
| 472 // -- [sp] : receiver | 464 // -- [sp] : receiver |
| 473 // ----------------------------------- | 465 // ----------------------------------- |
| 474 | 466 |
| 475 __ ldr(r3, MemOperand(sp, 0)); | 467 __ ldr(r3, MemOperand(sp, 0)); |
| 476 __ stm(db_w, sp, r2.bit() | r3.bit()); | 468 __ stm(db_w, sp, r2.bit() | r3.bit()); |
| 477 | 469 |
| 478 // Perform tail call to the entry. | 470 // Perform tail call to the entry. |
| 479 __ TailCallRuntime(f, 2, 1); | 471 __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1); |
| 480 } | 472 } |
| 481 | 473 |
| 482 | 474 |
| 483 // TODO(181): Implement map patching once loop nesting is tracked on the | 475 // TODO(181): Implement map patching once loop nesting is tracked on the |
| 484 // ARM platform so we can generate inlined fast-case code loads in | 476 // ARM platform so we can generate inlined fast-case code loads in |
| 485 // loops. | 477 // loops. |
| 486 void LoadIC::ClearInlinedVersion(Address address) {} | 478 void LoadIC::ClearInlinedVersion(Address address) {} |
| 487 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 479 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 488 return false; | 480 return false; |
| 489 } | 481 } |
| 490 | 482 |
| 491 void KeyedLoadIC::ClearInlinedVersion(Address address) {} | 483 void KeyedLoadIC::ClearInlinedVersion(Address address) {} |
| 492 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { | 484 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
| 493 return false; | 485 return false; |
| 494 } | 486 } |
| 495 | 487 |
| 496 void KeyedStoreIC::ClearInlinedVersion(Address address) {} | 488 void KeyedStoreIC::ClearInlinedVersion(Address address) {} |
| 497 void KeyedStoreIC::RestoreInlinedVersion(Address address) {} | 489 void KeyedStoreIC::RestoreInlinedVersion(Address address) {} |
| 498 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { | 490 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { |
| 499 return false; | 491 return false; |
| 500 } | 492 } |
| 501 | 493 |
| 502 | 494 |
| 503 Object* KeyedLoadIC_Miss(Arguments args); | 495 Object* KeyedLoadIC_Miss(Arguments args); |
| 504 | 496 |
| 505 | 497 |
| 506 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 498 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 507 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); | 499 // ---------- S t a t e -------------- |
| 500 // -- lr : return address |
| 501 // -- sp[0] : key |
| 502 // -- sp[4] : receiver |
| 503 // ----------------------------------- |
| 504 |
| 505 __ ldm(ia, sp, r2.bit() | r3.bit()); |
| 506 __ stm(db_w, sp, r2.bit() | r3.bit()); |
| 507 |
| 508 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1); |
| 508 } | 509 } |
| 509 | 510 |
| 510 | 511 |
| 511 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) { | 512 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 512 // ---------- S t a t e -------------- | 513 // ---------- S t a t e -------------- |
| 513 // -- lr : return address | 514 // -- lr : return address |
| 514 // -- sp[0] : key | 515 // -- sp[0] : key |
| 515 // -- sp[4] : receiver | 516 // -- sp[4] : receiver |
| 516 // ----------------------------------- | 517 // ----------------------------------- |
| 517 | 518 |
| 518 __ ldm(ia, sp, r2.bit() | r3.bit()); | 519 __ ldm(ia, sp, r2.bit() | r3.bit()); |
| 519 __ stm(db_w, sp, r2.bit() | r3.bit()); | 520 __ stm(db_w, sp, r2.bit() | r3.bit()); |
| 520 | 521 |
| 521 __ TailCallRuntime(f, 2, 1); | 522 __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2, 1); |
| 522 } | 523 } |
| 523 | 524 |
| 524 | 525 |
| 525 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 526 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 526 // ---------- S t a t e -------------- | 527 // ---------- S t a t e -------------- |
| 527 // -- lr : return address | 528 // -- lr : return address |
| 528 // -- sp[0] : key | 529 // -- sp[0] : key |
| 529 // -- sp[4] : receiver | 530 // -- sp[4] : receiver |
| 530 // ----------------------------------- | 531 // ----------------------------------- |
| 531 Label slow, fast; | 532 Label slow, fast; |
| 532 | 533 |
| 533 // Get the key and receiver object from the stack. | 534 // Get the key and receiver object from the stack. |
| 534 __ ldm(ia, sp, r0.bit() | r1.bit()); | 535 __ ldm(ia, sp, r0.bit() | r1.bit()); |
| 535 // Check that the key is a smi. | 536 |
| 536 __ tst(r0, Operand(kSmiTagMask)); | |
| 537 __ b(ne, &slow); | |
| 538 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | |
| 539 // Check that the object isn't a smi. | 537 // Check that the object isn't a smi. |
| 540 __ tst(r1, Operand(kSmiTagMask)); | 538 __ BranchOnSmi(r1, &slow); |
| 541 __ b(eq, &slow); | |
| 542 | |
| 543 // Get the map of the receiver. | 539 // Get the map of the receiver. |
| 544 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 540 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 545 | |
| 546 // Check bit field. | 541 // Check bit field. |
| 547 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); | 542 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| 548 __ tst(r3, Operand(kSlowCaseBitFieldMask)); | 543 __ tst(r3, Operand(kSlowCaseBitFieldMask)); |
| 549 __ b(ne, &slow); | 544 __ b(ne, &slow); |
| 550 // Check that the object is some kind of JS object EXCEPT JS Value type. | 545 // Check that the object is some kind of JS object EXCEPT JS Value type. |
| 551 // In the case that the object is a value-wrapper object, | 546 // In the case that the object is a value-wrapper object, |
| 552 // we enter the runtime system to make sure that indexing into string | 547 // we enter the runtime system to make sure that indexing into string |
| 553 // objects work as intended. | 548 // objects work as intended. |
| 554 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 549 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 555 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 550 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 556 __ cmp(r2, Operand(JS_OBJECT_TYPE)); | 551 __ cmp(r2, Operand(JS_OBJECT_TYPE)); |
| 557 __ b(lt, &slow); | 552 __ b(lt, &slow); |
| 558 | 553 |
| 554 // Check that the key is a smi. |
| 555 __ BranchOnNotSmi(r0, &slow); |
| 556 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
| 557 |
| 559 // Get the elements array of the object. | 558 // Get the elements array of the object. |
| 560 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 559 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 561 // Check that the object is in fast mode (not dictionary). | 560 // Check that the object is in fast mode (not dictionary). |
| 562 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 561 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 563 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 562 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 564 __ cmp(r3, ip); | 563 __ cmp(r3, ip); |
| 565 __ b(ne, &slow); | 564 __ b(ne, &slow); |
| 566 // Check that the key (index) is within bounds. | 565 // Check that the key (index) is within bounds. |
| 567 __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset)); | 566 __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset)); |
| 568 __ cmp(r0, Operand(r3)); | 567 __ cmp(r0, Operand(r3)); |
| 569 __ b(lo, &fast); | 568 __ b(lo, &fast); |
| 570 | 569 |
| 571 // Slow case: Push extra copies of the arguments (2). | 570 // Slow case: Push extra copies of the arguments (2). |
| 572 __ bind(&slow); | 571 __ bind(&slow); |
| 573 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1); | 572 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1); |
| 574 __ ldm(ia, sp, r0.bit() | r1.bit()); | 573 GenerateRuntimeGetProperty(masm); |
| 575 __ stm(db_w, sp, r0.bit() | r1.bit()); | |
| 576 // Do tail-call to runtime routine. | |
| 577 __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2, 1); | |
| 578 | 574 |
| 579 // Fast case: Do the load. | 575 // Fast case: Do the load. |
| 580 __ bind(&fast); | 576 __ bind(&fast); |
| 581 __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 577 __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 582 __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2)); | 578 __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2)); |
| 583 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 579 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 584 __ cmp(r0, ip); | 580 __ cmp(r0, ip); |
| 585 // In case the loaded value is the_hole we have to consult GetProperty | 581 // In case the loaded value is the_hole we have to consult GetProperty |
| 586 // to ensure the prototype chain is searched. | 582 // to ensure the prototype chain is searched. |
| 587 __ b(eq, &slow); | 583 __ b(eq, &slow); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 601 } | 597 } |
| 602 | 598 |
| 603 | 599 |
| 604 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, | 600 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, |
| 605 ExternalArrayType array_type) { | 601 ExternalArrayType array_type) { |
| 606 // TODO(476): port specialized code. | 602 // TODO(476): port specialized code. |
| 607 GenerateGeneric(masm); | 603 GenerateGeneric(masm); |
| 608 } | 604 } |
| 609 | 605 |
| 610 | 606 |
| 611 void KeyedStoreIC::Generate(MacroAssembler* masm, | 607 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 612 const ExternalReference& f) { | 608 // ---------- S t a t e -------------- |
| 609 // -- lr : return address |
| 610 // -- sp[0] : key |
| 611 // -- sp[4] : receiver |
| 612 // ----------------------------------- |
| 613 Label slow; |
| 614 |
| 615 // Get the key and receiver object from the stack. |
| 616 __ ldm(ia, sp, r0.bit() | r1.bit()); |
| 617 |
| 618 // Check that the receiver isn't a smi. |
| 619 __ BranchOnSmi(r1, &slow); |
| 620 |
| 621 // Check that the key is a smi. |
| 622 __ BranchOnNotSmi(r0, &slow); |
| 623 |
| 624 // Get the map of the receiver. |
| 625 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 626 |
| 627 // Check that it has indexed interceptor and access checks |
| 628 // are not enabled for this object. |
| 629 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| 630 __ and_(r3, r3, Operand(kSlowCaseBitFieldMask)); |
| 631 __ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor)); |
| 632 __ b(ne, &slow); |
| 633 |
| 634 // Everything is fine, call runtime. |
| 635 __ push(r1); // receiver |
| 636 __ push(r0); // key |
| 637 |
| 638 // Perform tail call to the entry. |
| 639 __ TailCallRuntime(ExternalReference( |
| 640 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
| 641 |
| 642 __ bind(&slow); |
| 643 GenerateMiss(masm); |
| 644 } |
| 645 |
| 646 |
| 647 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 613 // ---------- S t a t e -------------- | 648 // ---------- S t a t e -------------- |
| 614 // -- r0 : value | 649 // -- r0 : value |
| 615 // -- lr : return address | 650 // -- lr : return address |
| 616 // -- sp[0] : key | 651 // -- sp[0] : key |
| 617 // -- sp[1] : receiver | 652 // -- sp[1] : receiver |
| 618 // ----------------------------------- | 653 // ----------------------------------- |
| 619 | 654 |
| 620 __ ldm(ia, sp, r2.bit() | r3.bit()); | 655 __ ldm(ia, sp, r2.bit() | r3.bit()); |
| 621 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); | 656 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); |
| 622 | 657 |
| 623 __ TailCallRuntime(f, 3, 1); | 658 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1); |
| 659 } |
| 660 |
| 661 |
| 662 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 663 // ---------- S t a t e -------------- |
| 664 // -- r0 : value |
| 665 // -- lr : return address |
| 666 // -- sp[0] : key |
| 667 // -- sp[1] : receiver |
| 668 // ----------------------------------- |
| 669 __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object |
| 670 __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit()); |
| 671 |
| 672 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); |
| 624 } | 673 } |
| 625 | 674 |
| 626 | 675 |
| 627 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 676 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
| 628 // ---------- S t a t e -------------- | 677 // ---------- S t a t e -------------- |
| 629 // -- r0 : value | 678 // -- r0 : value |
| 630 // -- lr : return address | 679 // -- lr : return address |
| 631 // -- sp[0] : key | 680 // -- sp[0] : key |
| 632 // -- sp[1] : receiver | 681 // -- sp[1] : receiver |
| 633 // ----------------------------------- | 682 // ----------------------------------- |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // Untag the key (for checking against untagged length in the fixed array). | 717 // Untag the key (for checking against untagged length in the fixed array). |
| 669 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); | 718 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); |
| 670 // Compute address to store into and check array bounds. | 719 // Compute address to store into and check array bounds. |
| 671 __ add(r2, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 720 __ add(r2, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 672 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2)); | 721 __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2)); |
| 673 __ ldr(ip, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 722 __ ldr(ip, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
| 674 __ cmp(r1, Operand(ip)); | 723 __ cmp(r1, Operand(ip)); |
| 675 __ b(lo, &fast); | 724 __ b(lo, &fast); |
| 676 | 725 |
| 677 | 726 |
| 678 // Slow case: Push extra copies of the arguments (3). | 727 // Slow case: |
| 679 __ bind(&slow); | 728 __ bind(&slow); |
| 680 __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object | 729 GenerateRuntimeSetProperty(masm); |
| 681 __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit()); | |
| 682 // Do tail-call to runtime routine. | |
| 683 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); | |
| 684 | 730 |
| 685 // Extra capacity case: Check if there is extra capacity to | 731 // Extra capacity case: Check if there is extra capacity to |
| 686 // perform the store and update the length. Used for adding one | 732 // perform the store and update the length. Used for adding one |
| 687 // element to the array by writing to array[array.length]. | 733 // element to the array by writing to array[array.length]. |
| 688 // r0 == value, r1 == key, r2 == elements, r3 == object | 734 // r0 == value, r1 == key, r2 == elements, r3 == object |
| 689 __ bind(&extra); | 735 __ bind(&extra); |
| 690 __ b(ne, &slow); // do not leave holes in the array | 736 __ b(ne, &slow); // do not leave holes in the array |
| 691 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); // untag | 737 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); // untag |
| 692 __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset)); | 738 __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset)); |
| 693 __ cmp(r1, Operand(ip)); | 739 __ cmp(r1, Operand(ip)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 } | 790 } |
| 745 | 791 |
| 746 | 792 |
| 747 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 793 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, |
| 748 ExternalArrayType array_type) { | 794 ExternalArrayType array_type) { |
| 749 // TODO(476): port specialized code. | 795 // TODO(476): port specialized code. |
| 750 GenerateGeneric(masm); | 796 GenerateGeneric(masm); |
| 751 } | 797 } |
| 752 | 798 |
| 753 | 799 |
| 754 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) { | |
| 755 // ---------- S t a t e -------------- | |
| 756 // -- r0 : value | |
| 757 // -- lr : return address | |
| 758 // -- sp[0] : key | |
| 759 // -- sp[1] : receiver | |
| 760 // ----------- S t a t e ------------- | |
| 761 | |
| 762 __ ldm(ia, sp, r2.bit() | r3.bit()); | |
| 763 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); | |
| 764 | |
| 765 // Perform tail call to the entry. | |
| 766 __ TailCallRuntime( | |
| 767 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 768 } | |
| 769 | |
| 770 | |
| 771 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 800 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 772 // ----------- S t a t e ------------- | 801 // ----------- S t a t e ------------- |
| 773 // -- r0 : value | 802 // -- r0 : value |
| 803 // -- r1 : receiver |
| 774 // -- r2 : name | 804 // -- r2 : name |
| 775 // -- lr : return address | 805 // -- lr : return address |
| 776 // -- [sp] : receiver | |
| 777 // ----------------------------------- | 806 // ----------------------------------- |
| 778 | 807 |
| 779 // Get the receiver from the stack and probe the stub cache. | 808 // Get the receiver from the stack and probe the stub cache. |
| 780 __ ldr(r1, MemOperand(sp)); | |
| 781 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 809 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 782 NOT_IN_LOOP, | 810 NOT_IN_LOOP, |
| 783 MONOMORPHIC); | 811 MONOMORPHIC); |
| 784 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); | 812 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); |
| 785 | 813 |
| 786 // Cache miss: Jump to runtime. | 814 // Cache miss: Jump to runtime. |
| 787 GenerateMiss(masm); | 815 GenerateMiss(masm); |
| 788 } | 816 } |
| 789 | 817 |
| 790 | 818 |
| 791 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { | |
| 792 // ----------- S t a t e ------------- | |
| 793 // -- r0 : value | |
| 794 // -- r2 : name | |
| 795 // -- lr : return address | |
| 796 // -- [sp] : receiver | |
| 797 // ----------------------------------- | |
| 798 | |
| 799 __ ldr(r3, MemOperand(sp)); // copy receiver | |
| 800 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); | |
| 801 | |
| 802 // Perform tail call to the entry. | |
| 803 __ TailCallRuntime( | |
| 804 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 805 } | |
| 806 | |
| 807 | |
| 808 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 819 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 809 // ----------- S t a t e ------------- | 820 // ----------- S t a t e ------------- |
| 810 // -- r0 : value | 821 // -- r0 : value |
| 822 // -- r1 : receiver |
| 811 // -- r2 : name | 823 // -- r2 : name |
| 812 // -- lr : return address | 824 // -- lr : return address |
| 813 // -- [sp] : receiver | |
| 814 // ----------------------------------- | 825 // ----------------------------------- |
| 815 | 826 |
| 816 __ ldr(r3, MemOperand(sp)); // copy receiver | 827 __ push(r1); |
| 817 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); | 828 __ stm(db_w, sp, r2.bit() | r0.bit()); |
| 818 | 829 |
| 819 // Perform tail call to the entry. | 830 // Perform tail call to the entry. |
| 820 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); | 831 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); |
| 821 } | 832 } |
| 822 | 833 |
| 823 | 834 |
| 835 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 836 // ----------- S t a t e ------------- |
| 837 // -- r0 : value |
| 838 // -- r1 : receiver |
| 839 // -- r2 : name |
| 840 // -- lr : return address |
| 841 // ----------------------------------- |
| 842 // |
| 843 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 844 // (currently anything except for external and pixel arrays which means |
| 845 // anything with elements of FixedArray type.), but currently is restricted |
| 846 // to JSArray. |
| 847 // Value must be a number, but only smis are accepted as the most common case. |
| 848 |
| 849 Label miss; |
| 850 |
| 851 Register receiver = r1; |
| 852 Register value = r0; |
| 853 Register scratch = r3; |
| 854 |
| 855 // Check that the receiver isn't a smi. |
| 856 __ BranchOnSmi(receiver, &miss); |
| 857 |
| 858 // Check that the object is a JS array. |
| 859 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
| 860 __ b(ne, &miss); |
| 861 |
| 862 // Check that elements are FixedArray. |
| 863 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 864 __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); |
| 865 __ b(ne, &miss); |
| 866 |
| 867 // Check that value is a smi. |
| 868 __ BranchOnNotSmi(value, &miss); |
| 869 |
| 870 // Prepare tail call to StoreIC_ArrayLength. |
| 871 __ push(receiver); |
| 872 __ push(value); |
| 873 |
| 874 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ArrayLength)), 2, 1); |
| 875 |
| 876 __ bind(&miss); |
| 877 |
| 878 GenerateMiss(masm); |
| 879 } |
| 880 |
| 881 |
| 824 #undef __ | 882 #undef __ |
| 825 | 883 |
| 826 | 884 |
| 827 } } // namespace v8::internal | 885 } } // namespace v8::internal |
| OLD | NEW |