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

Side by Side Diff: src/ia32/macro-assembler-ia32.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/regexp-macro-assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 Register dst, 198 Register dst,
199 SaveFPRegsMode save_fp, 199 SaveFPRegsMode save_fp,
200 RememberedSetAction remembered_set_action, 200 RememberedSetAction remembered_set_action,
201 SmiCheck smi_check) { 201 SmiCheck smi_check) {
202 // First, check if a write barrier is even needed. The tests below 202 // First, check if a write barrier is even needed. The tests below
203 // catch stores of Smis. 203 // catch stores of Smis.
204 Label done; 204 Label done;
205 205
206 // Skip barrier if writing a smi. 206 // Skip barrier if writing a smi.
207 if (smi_check == INLINE_SMI_CHECK) { 207 if (smi_check == INLINE_SMI_CHECK) {
208 ASSERT_EQ(0, kSmiTag); 208 JumpIfSmi(value, &done, Label::kNear);
209 test(value, Immediate(kSmiTagMask));
210 j(zero, &done, Label::kNear);
211 } 209 }
212 210
213 // Although the object register is tagged, the offset is relative to the start 211 // Although the object register is tagged, the offset is relative to the start
214 // of the object, so so offset must be a multiple of kPointerSize. 212 // of the object, so so offset must be a multiple of kPointerSize.
215 ASSERT(IsAligned(offset, kPointerSize)); 213 ASSERT(IsAligned(offset, kPointerSize));
216 214
217 lea(dst, FieldOperand(object, offset)); 215 lea(dst, FieldOperand(object, offset));
218 if (emit_debug_code()) { 216 if (emit_debug_code()) {
219 Label ok; 217 Label ok;
220 test_b(Operand(dst), (1 << kPointerSizeLog2) - 1); 218 test_b(Operand(dst), (1 << kPointerSizeLog2) - 1);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 int3(); 260 int3();
263 bind(&ok); 261 bind(&ok);
264 } 262 }
265 263
266 // First, check if a write barrier is even needed. The tests below 264 // First, check if a write barrier is even needed. The tests below
267 // catch stores of Smis and stores into young gen. 265 // catch stores of Smis and stores into young gen.
268 Label done; 266 Label done;
269 267
270 if (smi_check == INLINE_SMI_CHECK) { 268 if (smi_check == INLINE_SMI_CHECK) {
271 // Skip barrier if writing a smi. 269 // Skip barrier if writing a smi.
272 ASSERT_EQ(0, kSmiTag); 270 JumpIfSmi(value, &done, Label::kNear);
273 test(value, Immediate(kSmiTagMask));
274 j(zero, &done, Label::kNear);
275 } 271 }
276 272
277 CheckPageFlag(value, 273 CheckPageFlag(value,
278 value, // Used as scratch. 274 value, // Used as scratch.
279 MemoryChunk::kPointersToHereAreInterestingMask, 275 MemoryChunk::kPointersToHereAreInterestingMask,
280 zero, 276 zero,
281 &done, 277 &done,
282 Label::kNear); 278 Label::kNear);
283 CheckPageFlag(object, 279 CheckPageFlag(object,
284 value, // Used as scratch. 280 value, // Used as scratch.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 CmpInstanceType(map, type); 355 CmpInstanceType(map, type);
360 } 356 }
361 357
362 358
363 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { 359 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
364 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), 360 cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
365 static_cast<int8_t>(type)); 361 static_cast<int8_t>(type));
366 } 362 }
367 363
368 364
365 void MacroAssembler::CheckFastElements(Register map,
366 Label* fail,
367 Label::Distance distance) {
368 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
369 cmpb(FieldOperand(map, Map::kBitField2Offset),
370 Map::kMaximumBitField2FastElementValue);
371 j(above, fail, distance);
372 }
373
374
369 void MacroAssembler::CheckMap(Register obj, 375 void MacroAssembler::CheckMap(Register obj,
370 Handle<Map> map, 376 Handle<Map> map,
371 Label* fail, 377 Label* fail,
372 SmiCheckType smi_check_type) { 378 SmiCheckType smi_check_type) {
373 if (smi_check_type == DO_SMI_CHECK) { 379 if (smi_check_type == DO_SMI_CHECK) {
374 JumpIfSmi(obj, fail); 380 JumpIfSmi(obj, fail);
375 } 381 }
376 cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map)); 382 cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
377 j(not_equal, fail); 383 j(not_equal, fail);
378 } 384 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 Label* fail) { 416 Label* fail) {
411 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 417 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
412 IsInstanceJSObjectType(map, scratch, fail); 418 IsInstanceJSObjectType(map, scratch, fail);
413 } 419 }
414 420
415 421
416 void MacroAssembler::IsInstanceJSObjectType(Register map, 422 void MacroAssembler::IsInstanceJSObjectType(Register map,
417 Register scratch, 423 Register scratch,
418 Label* fail) { 424 Label* fail) {
419 movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset)); 425 movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
420 sub(Operand(scratch), Immediate(FIRST_JS_OBJECT_TYPE)); 426 sub(Operand(scratch), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
421 cmp(scratch, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); 427 cmp(scratch,
428 LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
422 j(above, fail); 429 j(above, fail);
423 } 430 }
424 431
425 432
426 void MacroAssembler::FCmp() { 433 void MacroAssembler::FCmp() {
427 if (CpuFeatures::IsSupported(CMOV)) { 434 if (CpuFeatures::IsSupported(CMOV)) {
428 fucomip(); 435 fucomip();
429 ffree(0); 436 ffree(0);
430 fincstp(); 437 fincstp();
431 } else { 438 } else {
432 fucompp(); 439 fucompp();
433 push(eax); 440 push(eax);
434 fnstsw_ax(); 441 fnstsw_ax();
435 sahf(); 442 sahf();
436 pop(eax); 443 pop(eax);
437 } 444 }
438 } 445 }
439 446
440 447
441 void MacroAssembler::AbortIfNotNumber(Register object) { 448 void MacroAssembler::AbortIfNotNumber(Register object) {
442 Label ok; 449 Label ok;
443 test(object, Immediate(kSmiTagMask)); 450 JumpIfSmi(object, &ok);
444 j(zero, &ok);
445 cmp(FieldOperand(object, HeapObject::kMapOffset), 451 cmp(FieldOperand(object, HeapObject::kMapOffset),
446 isolate()->factory()->heap_number_map()); 452 isolate()->factory()->heap_number_map());
447 Assert(equal, "Operand not a number"); 453 Assert(equal, "Operand not a number");
448 bind(&ok); 454 bind(&ok);
449 } 455 }
450 456
451 457
452 void MacroAssembler::AbortIfNotSmi(Register object) { 458 void MacroAssembler::AbortIfNotSmi(Register object) {
453 test(object, Immediate(kSmiTagMask)); 459 test(object, Immediate(kSmiTagMask));
454 Assert(equal, "Operand is not a smi"); 460 Assert(equal, "Operand is not a smi");
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 Context::SECURITY_TOKEN_INDEX * kPointerSize; 812 Context::SECURITY_TOKEN_INDEX * kPointerSize;
807 mov(scratch, FieldOperand(scratch, token_offset)); 813 mov(scratch, FieldOperand(scratch, token_offset));
808 cmp(scratch, FieldOperand(holder_reg, token_offset)); 814 cmp(scratch, FieldOperand(holder_reg, token_offset));
809 pop(holder_reg); 815 pop(holder_reg);
810 j(not_equal, miss); 816 j(not_equal, miss);
811 817
812 bind(&same_contexts); 818 bind(&same_contexts);
813 } 819 }
814 820
815 821
822 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
823 Register elements,
824 Register key,
825 Register r0,
826 Register r1,
827 Register r2,
828 Register result) {
829 // Register use:
830 //
831 // elements - holds the slow-case elements of the receiver and is unchanged.
832 //
833 // key - holds the smi key on entry and is unchanged.
834 //
835 // Scratch registers:
836 //
837 // r0 - holds the untagged key on entry and holds the hash once computed.
838 //
839 // r1 - used to hold the capacity mask of the dictionary
840 //
841 // r2 - used for the index into the dictionary.
842 //
843 // result - holds the result on exit if the load succeeds and we fall through.
844
845 Label done;
846
847 // Compute the hash code from the untagged key. This must be kept in sync
848 // with ComputeIntegerHash in utils.h.
849 //
850 // hash = ~hash + (hash << 15);
851 mov(r1, r0);
852 not_(r0);
853 shl(r1, 15);
854 add(r0, Operand(r1));
855 // hash = hash ^ (hash >> 12);
856 mov(r1, r0);
857 shr(r1, 12);
858 xor_(r0, Operand(r1));
859 // hash = hash + (hash << 2);
860 lea(r0, Operand(r0, r0, times_4, 0));
861 // hash = hash ^ (hash >> 4);
862 mov(r1, r0);
863 shr(r1, 4);
864 xor_(r0, Operand(r1));
865 // hash = hash * 2057;
866 imul(r0, r0, 2057);
867 // hash = hash ^ (hash >> 16);
868 mov(r1, r0);
869 shr(r1, 16);
870 xor_(r0, Operand(r1));
871
872 // Compute capacity mask.
873 mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset));
874 shr(r1, kSmiTagSize); // convert smi to int
875 dec(r1);
876
877 // Generate an unrolled loop that performs a few probes before giving up.
878 const int kProbes = 4;
879 for (int i = 0; i < kProbes; i++) {
880 // Use r2 for index calculations and keep the hash intact in r0.
881 mov(r2, r0);
882 // Compute the masked index: (hash + i + i * i) & mask.
883 if (i > 0) {
884 add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
885 }
886 and_(r2, Operand(r1));
887
888 // Scale the index by multiplying by the entry size.
889 ASSERT(NumberDictionary::kEntrySize == 3);
890 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
891
892 // Check if the key matches.
893 cmp(key, FieldOperand(elements,
894 r2,
895 times_pointer_size,
896 NumberDictionary::kElementsStartOffset));
897 if (i != (kProbes - 1)) {
898 j(equal, &done);
899 } else {
900 j(not_equal, miss);
901 }
902 }
903
904 bind(&done);
905 // Check that the value is a normal propety.
906 const int kDetailsOffset =
907 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
908 ASSERT_EQ(NORMAL, 0);
909 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
910 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
911 j(not_zero, miss);
912
913 // Get the value at the masked, scaled index.
914 const int kValueOffset =
915 NumberDictionary::kElementsStartOffset + kPointerSize;
916 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
917 }
918
919
816 void MacroAssembler::LoadAllocationTopHelper(Register result, 920 void MacroAssembler::LoadAllocationTopHelper(Register result,
817 Register scratch, 921 Register scratch,
818 AllocationFlags flags) { 922 AllocationFlags flags) {
819 ExternalReference new_space_allocation_top = 923 ExternalReference new_space_allocation_top =
820 ExternalReference::new_space_allocation_top_address(isolate()); 924 ExternalReference::new_space_allocation_top_address(isolate());
821 925
822 // Just return if allocation top is already known. 926 // Just return if allocation top is already known.
823 if ((flags & RESULT_CONTAINS_TOP) != 0) { 927 if ((flags & RESULT_CONTAINS_TOP) != 0) {
824 // No use of scratch if allocation top is provided. 928 // No use of scratch if allocation top is provided.
825 ASSERT(scratch.is(no_reg)); 929 ASSERT(scratch.is(no_reg));
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
1245 j(sign, then_label); 1349 j(sign, then_label);
1246 bind(&ok); 1350 bind(&ok);
1247 } 1351 }
1248 1352
1249 1353
1250 void MacroAssembler::TryGetFunctionPrototype(Register function, 1354 void MacroAssembler::TryGetFunctionPrototype(Register function,
1251 Register result, 1355 Register result,
1252 Register scratch, 1356 Register scratch,
1253 Label* miss) { 1357 Label* miss) {
1254 // Check that the receiver isn't a smi. 1358 // Check that the receiver isn't a smi.
1255 test(function, Immediate(kSmiTagMask)); 1359 JumpIfSmi(function, miss);
1256 j(zero, miss);
1257 1360
1258 // Check that the function really is a function. 1361 // Check that the function really is a function.
1259 CmpObjectType(function, JS_FUNCTION_TYPE, result); 1362 CmpObjectType(function, JS_FUNCTION_TYPE, result);
1260 j(not_equal, miss); 1363 j(not_equal, miss);
1261 1364
1262 // Make sure that the function has an instance prototype. 1365 // Make sure that the function has an instance prototype.
1263 Label non_instance; 1366 Label non_instance;
1264 movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset)); 1367 movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
1265 test(scratch, Immediate(1 << Map::kHasNonInstancePrototype)); 1368 test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
1266 j(not_zero, &non_instance); 1369 j(not_zero, &non_instance);
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1485 static const bool kReturnHandlesDirectly = false; 1588 static const bool kReturnHandlesDirectly = false;
1486 #endif 1589 #endif
1487 1590
1488 1591
1489 Operand ApiParameterOperand(int index) { 1592 Operand ApiParameterOperand(int index) {
1490 return Operand( 1593 return Operand(
1491 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); 1594 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize);
1492 } 1595 }
1493 1596
1494 1597
1495 void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) { 1598 void MacroAssembler::PrepareCallApiFunction(int argc) {
1496 if (kReturnHandlesDirectly) { 1599 if (kReturnHandlesDirectly) {
1497 EnterApiExitFrame(argc); 1600 EnterApiExitFrame(argc);
1498 // When handles are returned directly we don't have to allocate extra 1601 // When handles are returned directly we don't have to allocate extra
1499 // space for and pass an out parameter. 1602 // space for and pass an out parameter.
1603 if (emit_debug_code()) {
1604 mov(esi, Immediate(BitCast<int32_t>(kZapValue)));
1605 }
1500 } else { 1606 } else {
1501 // We allocate two additional slots: return value and pointer to it. 1607 // We allocate two additional slots: return value and pointer to it.
1502 EnterApiExitFrame(argc + 2); 1608 EnterApiExitFrame(argc + 2);
1503 1609
1504 // The argument slots are filled as follows: 1610 // The argument slots are filled as follows:
1505 // 1611 //
1506 // n + 1: output cell 1612 // n + 1: output slot
1507 // n: arg n 1613 // n: arg n
1508 // ... 1614 // ...
1509 // 1: arg1 1615 // 1: arg1
1510 // 0: pointer to the output cell 1616 // 0: pointer to the output slot
1511 //
1512 // Note that this is one more "argument" than the function expects
1513 // so the out cell will have to be popped explicitly after returning
1514 // from the function. The out cell contains Handle.
1515 1617
1516 // pointer to out cell. 1618 lea(esi, Operand(esp, (argc + 1) * kPointerSize));
1517 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); 1619 mov(Operand(esp, 0 * kPointerSize), esi);
1518 mov(Operand(esp, 0 * kPointerSize), scratch); // output.
1519 if (emit_debug_code()) { 1620 if (emit_debug_code()) {
1520 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. 1621 mov(Operand(esi, 0), Immediate(0));
1521 } 1622 }
1522 } 1623 }
1523 } 1624 }
1524 1625
1525 1626
1526 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, 1627 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
1527 int stack_space) { 1628 int stack_space) {
1528 ExternalReference next_address = 1629 ExternalReference next_address =
1529 ExternalReference::handle_scope_next_address(); 1630 ExternalReference::handle_scope_next_address();
1530 ExternalReference limit_address = 1631 ExternalReference limit_address =
1531 ExternalReference::handle_scope_limit_address(); 1632 ExternalReference::handle_scope_limit_address();
1532 ExternalReference level_address = 1633 ExternalReference level_address =
1533 ExternalReference::handle_scope_level_address(); 1634 ExternalReference::handle_scope_level_address();
1534 1635
1535 // Allocate HandleScope in callee-save registers. 1636 // Allocate HandleScope in callee-save registers.
1536 mov(ebx, Operand::StaticVariable(next_address)); 1637 mov(ebx, Operand::StaticVariable(next_address));
1537 mov(edi, Operand::StaticVariable(limit_address)); 1638 mov(edi, Operand::StaticVariable(limit_address));
1538 add(Operand::StaticVariable(level_address), Immediate(1)); 1639 add(Operand::StaticVariable(level_address), Immediate(1));
1539 1640
1540 // Call the api function! 1641 // Call the api function!
1541 call(function->address(), RelocInfo::RUNTIME_ENTRY); 1642 call(function->address(), RelocInfo::RUNTIME_ENTRY);
1542 1643
1543 if (!kReturnHandlesDirectly) { 1644 if (!kReturnHandlesDirectly) {
1544 // The returned value is a pointer to the handle holding the result. 1645 // PrepareCallApiFunction saved pointer to the output slot into
1545 // Dereference this to get to the location. 1646 // callee-save register esi.
1546 mov(eax, Operand(eax, 0)); 1647 mov(eax, Operand(esi, 0));
1547 } 1648 }
1548 1649
1549 Label empty_handle; 1650 Label empty_handle;
1550 Label prologue; 1651 Label prologue;
1551 Label promote_scheduled_exception; 1652 Label promote_scheduled_exception;
1552 Label delete_allocated_handles; 1653 Label delete_allocated_handles;
1553 Label leave_exit_frame; 1654 Label leave_exit_frame;
1554 1655
1555 // Check if the result handle holds 0. 1656 // Check if the result handle holds 0.
1556 test(eax, Operand(eax)); 1657 test(eax, Operand(eax));
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 1871
1771 ParameterCount expected(ebx); 1872 ParameterCount expected(ebx);
1772 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 1873 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
1773 expected, actual, flag, call_wrapper, call_kind); 1874 expected, actual, flag, call_wrapper, call_kind);
1774 } 1875 }
1775 1876
1776 1877
1777 void MacroAssembler::InvokeFunction(JSFunction* function, 1878 void MacroAssembler::InvokeFunction(JSFunction* function,
1778 const ParameterCount& actual, 1879 const ParameterCount& actual,
1779 InvokeFlag flag, 1880 InvokeFlag flag,
1780 const CallWrapper& call_wrapper) { 1881 const CallWrapper& call_wrapper,
1882 CallKind call_kind) {
1781 ASSERT(function->is_compiled()); 1883 ASSERT(function->is_compiled());
1782 // Get the function and setup the context. 1884 // Get the function and setup the context.
1783 mov(edi, Immediate(Handle<JSFunction>(function))); 1885 mov(edi, Immediate(Handle<JSFunction>(function)));
1784 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 1886 mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1785 1887
1786 ParameterCount expected(function->shared()->formal_parameter_count()); 1888 ParameterCount expected(function->shared()->formal_parameter_count());
1787 if (V8::UseCrankshaft()) { 1889 if (V8::UseCrankshaft()) {
1788 // TODO(kasperl): For now, we always call indirectly through the 1890 // TODO(kasperl): For now, we always call indirectly through the
1789 // code field in the function to allow recompilation to take effect 1891 // code field in the function to allow recompilation to take effect
1790 // without changing any of the call sites. 1892 // without changing any of the call sites.
1791 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 1893 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
1792 expected, actual, flag, call_wrapper); 1894 expected, actual, flag, call_wrapper, call_kind);
1793 } else { 1895 } else {
1794 Handle<Code> code(function->code()); 1896 Handle<Code> code(function->code());
1795 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, 1897 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET,
1796 flag, call_wrapper); 1898 flag, call_wrapper, call_kind);
1797 } 1899 }
1798 } 1900 }
1799 1901
1800 1902
1801 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 1903 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
1802 InvokeFlag flag, 1904 InvokeFlag flag,
1803 const CallWrapper& call_wrapper) { 1905 const CallWrapper& call_wrapper) {
1804 // Calls are not allowed in some stubs. 1906 // Calls are not allowed in some stubs.
1805 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); 1907 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
1806 1908
1807 // Rely on the assertion to check that the number of provided 1909 // Rely on the assertion to check that the number of provided
1808 // arguments match the expected number of arguments. Fake a 1910 // arguments match the expected number of arguments. Fake a
1809 // parameter count to avoid emitting code to do the check. 1911 // parameter count to avoid emitting code to do the check.
1810 ParameterCount expected(0); 1912 ParameterCount expected(0);
1811 GetBuiltinFunction(edi, id); 1913 GetBuiltinFunction(edi, id);
1812 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 1914 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
1813 expected, expected, flag, call_wrapper); 1915 expected, expected, flag, call_wrapper, CALL_AS_METHOD);
1814 } 1916 }
1815 1917
1816 void MacroAssembler::GetBuiltinFunction(Register target, 1918 void MacroAssembler::GetBuiltinFunction(Register target,
1817 Builtins::JavaScript id) { 1919 Builtins::JavaScript id) {
1818 // Load the JavaScript builtin function from the builtins object. 1920 // Load the JavaScript builtin function from the builtins object.
1819 mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 1921 mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
1820 mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); 1922 mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
1821 mov(target, FieldOperand(target, 1923 mov(target, FieldOperand(target,
1822 JSBuiltinsObject::OffsetOfFunctionWithId(id))); 1924 JSBuiltinsObject::OffsetOfFunctionWithId(id)));
1823 } 1925 }
1824 1926
1825 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 1927 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
1826 ASSERT(!target.is(edi)); 1928 ASSERT(!target.is(edi));
1827 // Load the JavaScript builtin function from the builtins object. 1929 // Load the JavaScript builtin function from the builtins object.
1828 GetBuiltinFunction(edi, id); 1930 GetBuiltinFunction(edi, id);
1829 // Load the code entry point from the function into the target register. 1931 // Load the code entry point from the function into the target register.
1830 mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 1932 mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
1831 } 1933 }
1832 1934
1833 1935
1834 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { 1936 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
1835 if (context_chain_length > 0) { 1937 if (context_chain_length > 0) {
1836 // Move up the chain of contexts to the context containing the slot. 1938 // Move up the chain of contexts to the context containing the slot.
1837 mov(dst, Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); 1939 mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
1838 // Load the function context (which is the incoming, outer context).
1839 mov(dst, FieldOperand(dst, JSFunction::kContextOffset));
1840 for (int i = 1; i < context_chain_length; i++) { 1940 for (int i = 1; i < context_chain_length; i++) {
1841 mov(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 1941 mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
1842 mov(dst, FieldOperand(dst, JSFunction::kContextOffset));
1843 } 1942 }
1844 } else { 1943 } else {
1845 // Slot is in the current function context. Move it into the 1944 // Slot is in the current function context. Move it into the
1846 // destination register in case we store into it (the write barrier 1945 // destination register in case we store into it (the write barrier
1847 // cannot be allowed to destroy the context in esi). 1946 // cannot be allowed to destroy the context in esi).
1848 mov(dst, esi); 1947 mov(dst, esi);
1849 } 1948 }
1850 1949
1851 // We should not have found a 'with' context by walking the context chain 1950 // We should not have found a with context by walking the context chain
1852 // (i.e., the static scope chain and runtime context chain do not agree). 1951 // (i.e., the static scope chain and runtime context chain do not agree).
1853 // A variable occurring in such a scope should have slot type LOOKUP and 1952 // A variable occurring in such a scope should have slot type LOOKUP and
1854 // not CONTEXT. 1953 // not CONTEXT.
1855 if (emit_debug_code()) { 1954 if (emit_debug_code()) {
1856 cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 1955 cmp(FieldOperand(dst, HeapObject::kMapOffset),
1857 Check(equal, "Yo dawg, I heard you liked function contexts " 1956 isolate()->factory()->with_context_map());
1858 "so I put function contexts in all your contexts"); 1957 Check(not_equal, "Variable resolved to with context.");
1859 } 1958 }
1860 } 1959 }
1861 1960
1862 1961
1863 void MacroAssembler::LoadGlobalFunction(int index, Register function) { 1962 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
1864 // Load the global or builtins object from the current context. 1963 // Load the global or builtins object from the current context.
1865 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 1964 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
1866 // Load the global context from the global or builtins object. 1965 // Load the global context from the global or builtins object.
1867 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); 1966 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset));
1868 // Load the function from the global context. 1967 // Load the function from the global context.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2127 2226
2128 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, 2227 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
2129 Register object2, 2228 Register object2,
2130 Register scratch1, 2229 Register scratch1,
2131 Register scratch2, 2230 Register scratch2,
2132 Label* failure) { 2231 Label* failure) {
2133 // Check that both objects are not smis. 2232 // Check that both objects are not smis.
2134 ASSERT_EQ(0, kSmiTag); 2233 ASSERT_EQ(0, kSmiTag);
2135 mov(scratch1, Operand(object1)); 2234 mov(scratch1, Operand(object1));
2136 and_(scratch1, Operand(object2)); 2235 and_(scratch1, Operand(object2));
2137 test(scratch1, Immediate(kSmiTagMask)); 2236 JumpIfSmi(scratch1, failure);
2138 j(zero, failure);
2139 2237
2140 // Load instance type for both strings. 2238 // Load instance type for both strings.
2141 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); 2239 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2142 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); 2240 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2143 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 2241 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2144 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 2242 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2145 2243
2146 // Check that both are flat ascii strings. 2244 // Check that both are flat ascii strings.
2147 const int kFlatAsciiStringMask = 2245 const int kFlatAsciiStringMask =
2148 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2246 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
2414 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); 2512 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
2415 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), 2513 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
2416 length); 2514 length);
2417 2515
2418 bind(&done); 2516 bind(&done);
2419 } 2517 }
2420 2518
2421 } } // namespace v8::internal 2519 } } // namespace v8::internal
2422 2520
2423 #endif // V8_TARGET_ARCH_IA32 2521 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/regexp-macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698