| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 } | 671 } |
| 672 } | 672 } |
| 673 | 673 |
| 674 | 674 |
| 675 void MacroAssembler::AssertNumber(Register object) { | 675 void MacroAssembler::AssertNumber(Register object) { |
| 676 if (emit_debug_code()) { | 676 if (emit_debug_code()) { |
| 677 Label ok; | 677 Label ok; |
| 678 JumpIfSmi(object, &ok); | 678 JumpIfSmi(object, &ok); |
| 679 cmp(FieldOperand(object, HeapObject::kMapOffset), | 679 cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 680 isolate()->factory()->heap_number_map()); | 680 isolate()->factory()->heap_number_map()); |
| 681 Check(equal, kOperandNotANumber); | 681 Check(equal, "Operand not a number"); |
| 682 bind(&ok); | 682 bind(&ok); |
| 683 } | 683 } |
| 684 } | 684 } |
| 685 | 685 |
| 686 | 686 |
| 687 void MacroAssembler::AssertSmi(Register object) { | 687 void MacroAssembler::AssertSmi(Register object) { |
| 688 if (emit_debug_code()) { | 688 if (emit_debug_code()) { |
| 689 test(object, Immediate(kSmiTagMask)); | 689 test(object, Immediate(kSmiTagMask)); |
| 690 Check(equal, kOperandIsNotASmi); | 690 Check(equal, "Operand is not a smi"); |
| 691 } | 691 } |
| 692 } | 692 } |
| 693 | 693 |
| 694 | 694 |
| 695 void MacroAssembler::AssertString(Register object) { | 695 void MacroAssembler::AssertString(Register object) { |
| 696 if (emit_debug_code()) { | 696 if (emit_debug_code()) { |
| 697 test(object, Immediate(kSmiTagMask)); | 697 test(object, Immediate(kSmiTagMask)); |
| 698 Check(not_equal, kOperandIsASmiAndNotAString); | 698 Check(not_equal, "Operand is a smi and not a string"); |
| 699 push(object); | 699 push(object); |
| 700 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | 700 mov(object, FieldOperand(object, HeapObject::kMapOffset)); |
| 701 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | 701 CmpInstanceType(object, FIRST_NONSTRING_TYPE); |
| 702 pop(object); | 702 pop(object); |
| 703 Check(below, kOperandIsNotAString); | 703 Check(below, "Operand is not a string"); |
| 704 } | 704 } |
| 705 } | 705 } |
| 706 | 706 |
| 707 | 707 |
| 708 void MacroAssembler::AssertName(Register object) { | 708 void MacroAssembler::AssertName(Register object) { |
| 709 if (emit_debug_code()) { | 709 if (emit_debug_code()) { |
| 710 test(object, Immediate(kSmiTagMask)); | 710 test(object, Immediate(kSmiTagMask)); |
| 711 Check(not_equal, kOperandIsASmiAndNotAName); | 711 Check(not_equal, "Operand is a smi and not a name"); |
| 712 push(object); | 712 push(object); |
| 713 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | 713 mov(object, FieldOperand(object, HeapObject::kMapOffset)); |
| 714 CmpInstanceType(object, LAST_NAME_TYPE); | 714 CmpInstanceType(object, LAST_NAME_TYPE); |
| 715 pop(object); | 715 pop(object); |
| 716 Check(below_equal, kOperandIsNotAName); | 716 Check(below_equal, "Operand is not a name"); |
| 717 } | 717 } |
| 718 } | 718 } |
| 719 | 719 |
| 720 | 720 |
| 721 void MacroAssembler::AssertNotSmi(Register object) { | 721 void MacroAssembler::AssertNotSmi(Register object) { |
| 722 if (emit_debug_code()) { | 722 if (emit_debug_code()) { |
| 723 test(object, Immediate(kSmiTagMask)); | 723 test(object, Immediate(kSmiTagMask)); |
| 724 Check(not_equal, kOperandIsASmi); | 724 Check(not_equal, "Operand is a smi"); |
| 725 } | 725 } |
| 726 } | 726 } |
| 727 | 727 |
| 728 | 728 |
| 729 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 729 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 730 push(ebp); | 730 push(ebp); |
| 731 mov(ebp, esp); | 731 mov(ebp, esp); |
| 732 push(esi); | 732 push(esi); |
| 733 push(Immediate(Smi::FromInt(type))); | 733 push(Immediate(Smi::FromInt(type))); |
| 734 push(Immediate(CodeObject())); | 734 push(Immediate(CodeObject())); |
| 735 if (emit_debug_code()) { | 735 if (emit_debug_code()) { |
| 736 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); | 736 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); |
| 737 Check(not_equal, kCodeObjectNotProperlyPatched); | 737 Check(not_equal, "code object not properly patched"); |
| 738 } | 738 } |
| 739 } | 739 } |
| 740 | 740 |
| 741 | 741 |
| 742 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 742 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 743 if (emit_debug_code()) { | 743 if (emit_debug_code()) { |
| 744 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 744 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
| 745 Immediate(Smi::FromInt(type))); | 745 Immediate(Smi::FromInt(type))); |
| 746 Check(equal, kStackFrameTypesMustMatch); | 746 Check(equal, "stack frame types must match"); |
| 747 } | 747 } |
| 748 leave(); | 748 leave(); |
| 749 } | 749 } |
| 750 | 750 |
| 751 | 751 |
| 752 void MacroAssembler::EnterExitFramePrologue() { | 752 void MacroAssembler::EnterExitFramePrologue() { |
| 753 // Set up the frame structure on the stack. | 753 // Set up the frame structure on the stack. |
| 754 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 754 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
| 755 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 755 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
| 756 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 756 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 ASSERT(!holder_reg.is(scratch1)); | 1017 ASSERT(!holder_reg.is(scratch1)); |
| 1018 ASSERT(!holder_reg.is(scratch2)); | 1018 ASSERT(!holder_reg.is(scratch2)); |
| 1019 ASSERT(!scratch1.is(scratch2)); | 1019 ASSERT(!scratch1.is(scratch2)); |
| 1020 | 1020 |
| 1021 // Load current lexical context from the stack frame. | 1021 // Load current lexical context from the stack frame. |
| 1022 mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1022 mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1023 | 1023 |
| 1024 // When generating debug code, make sure the lexical context is set. | 1024 // When generating debug code, make sure the lexical context is set. |
| 1025 if (emit_debug_code()) { | 1025 if (emit_debug_code()) { |
| 1026 cmp(scratch1, Immediate(0)); | 1026 cmp(scratch1, Immediate(0)); |
| 1027 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); | 1027 Check(not_equal, "we should not have an empty lexical context"); |
| 1028 } | 1028 } |
| 1029 // Load the native context of the current context. | 1029 // Load the native context of the current context. |
| 1030 int offset = | 1030 int offset = |
| 1031 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; | 1031 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; |
| 1032 mov(scratch1, FieldOperand(scratch1, offset)); | 1032 mov(scratch1, FieldOperand(scratch1, offset)); |
| 1033 mov(scratch1, FieldOperand(scratch1, GlobalObject::kNativeContextOffset)); | 1033 mov(scratch1, FieldOperand(scratch1, GlobalObject::kNativeContextOffset)); |
| 1034 | 1034 |
| 1035 // Check the context is a native context. | 1035 // Check the context is a native context. |
| 1036 if (emit_debug_code()) { | 1036 if (emit_debug_code()) { |
| 1037 // Read the first word and compare to native_context_map. | 1037 // Read the first word and compare to native_context_map. |
| 1038 cmp(FieldOperand(scratch1, HeapObject::kMapOffset), | 1038 cmp(FieldOperand(scratch1, HeapObject::kMapOffset), |
| 1039 isolate()->factory()->native_context_map()); | 1039 isolate()->factory()->native_context_map()); |
| 1040 Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); | 1040 Check(equal, "JSGlobalObject::native_context should be a native context."); |
| 1041 } | 1041 } |
| 1042 | 1042 |
| 1043 // Check if both contexts are the same. | 1043 // Check if both contexts are the same. |
| 1044 cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 1044 cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 1045 j(equal, &same_contexts); | 1045 j(equal, &same_contexts); |
| 1046 | 1046 |
| 1047 // Compare security tokens, save holder_reg on the stack so we can use it | 1047 // Compare security tokens, save holder_reg on the stack so we can use it |
| 1048 // as a temporary register. | 1048 // as a temporary register. |
| 1049 // | 1049 // |
| 1050 // Check that the security token in the calling global object is | 1050 // Check that the security token in the calling global object is |
| 1051 // compatible with the security token in the receiving global | 1051 // compatible with the security token in the receiving global |
| 1052 // object. | 1052 // object. |
| 1053 mov(scratch2, | 1053 mov(scratch2, |
| 1054 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 1054 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 1055 | 1055 |
| 1056 // Check the context is a native context. | 1056 // Check the context is a native context. |
| 1057 if (emit_debug_code()) { | 1057 if (emit_debug_code()) { |
| 1058 cmp(scratch2, isolate()->factory()->null_value()); | 1058 cmp(scratch2, isolate()->factory()->null_value()); |
| 1059 Check(not_equal, kJSGlobalProxyContextShouldNotBeNull); | 1059 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 1060 | 1060 |
| 1061 // Read the first word and compare to native_context_map(), | 1061 // Read the first word and compare to native_context_map(), |
| 1062 cmp(FieldOperand(scratch2, HeapObject::kMapOffset), | 1062 cmp(FieldOperand(scratch2, HeapObject::kMapOffset), |
| 1063 isolate()->factory()->native_context_map()); | 1063 isolate()->factory()->native_context_map()); |
| 1064 Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); | 1064 Check(equal, "JSGlobalObject::native_context should be a native context."); |
| 1065 } | 1065 } |
| 1066 | 1066 |
| 1067 int token_offset = Context::kHeaderSize + | 1067 int token_offset = Context::kHeaderSize + |
| 1068 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 1068 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 1069 mov(scratch1, FieldOperand(scratch1, token_offset)); | 1069 mov(scratch1, FieldOperand(scratch1, token_offset)); |
| 1070 cmp(scratch1, FieldOperand(scratch2, token_offset)); | 1070 cmp(scratch1, FieldOperand(scratch2, token_offset)); |
| 1071 j(not_equal, miss); | 1071 j(not_equal, miss); |
| 1072 | 1072 |
| 1073 bind(&same_contexts); | 1073 bind(&same_contexts); |
| 1074 } | 1074 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 ExternalReference allocation_top = | 1199 ExternalReference allocation_top = |
| 1200 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1200 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 1201 | 1201 |
| 1202 // Just return if allocation top is already known. | 1202 // Just return if allocation top is already known. |
| 1203 if ((flags & RESULT_CONTAINS_TOP) != 0) { | 1203 if ((flags & RESULT_CONTAINS_TOP) != 0) { |
| 1204 // No use of scratch if allocation top is provided. | 1204 // No use of scratch if allocation top is provided. |
| 1205 ASSERT(scratch.is(no_reg)); | 1205 ASSERT(scratch.is(no_reg)); |
| 1206 #ifdef DEBUG | 1206 #ifdef DEBUG |
| 1207 // Assert that result actually contains top on entry. | 1207 // Assert that result actually contains top on entry. |
| 1208 cmp(result, Operand::StaticVariable(allocation_top)); | 1208 cmp(result, Operand::StaticVariable(allocation_top)); |
| 1209 Check(equal, kUnexpectedAllocationTop); | 1209 Check(equal, "Unexpected allocation top"); |
| 1210 #endif | 1210 #endif |
| 1211 return; | 1211 return; |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 // Move address of new object to result. Use scratch register if available. | 1214 // Move address of new object to result. Use scratch register if available. |
| 1215 if (scratch.is(no_reg)) { | 1215 if (scratch.is(no_reg)) { |
| 1216 mov(result, Operand::StaticVariable(allocation_top)); | 1216 mov(result, Operand::StaticVariable(allocation_top)); |
| 1217 } else { | 1217 } else { |
| 1218 mov(scratch, Immediate(allocation_top)); | 1218 mov(scratch, Immediate(allocation_top)); |
| 1219 mov(result, Operand(scratch, 0)); | 1219 mov(result, Operand(scratch, 0)); |
| 1220 } | 1220 } |
| 1221 } | 1221 } |
| 1222 | 1222 |
| 1223 | 1223 |
| 1224 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 1224 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 1225 Register scratch, | 1225 Register scratch, |
| 1226 AllocationFlags flags) { | 1226 AllocationFlags flags) { |
| 1227 if (emit_debug_code()) { | 1227 if (emit_debug_code()) { |
| 1228 test(result_end, Immediate(kObjectAlignmentMask)); | 1228 test(result_end, Immediate(kObjectAlignmentMask)); |
| 1229 Check(zero, kUnalignedAllocationInNewSpace); | 1229 Check(zero, "Unaligned allocation in new space"); |
| 1230 } | 1230 } |
| 1231 | 1231 |
| 1232 ExternalReference allocation_top = | 1232 ExternalReference allocation_top = |
| 1233 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1233 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 1234 | 1234 |
| 1235 // Update new top. Use scratch if available. | 1235 // Update new top. Use scratch if available. |
| 1236 if (scratch.is(no_reg)) { | 1236 if (scratch.is(no_reg)) { |
| 1237 mov(Operand::StaticVariable(allocation_top), result_end); | 1237 mov(Operand::StaticVariable(allocation_top), result_end); |
| 1238 } else { | 1238 } else { |
| 1239 mov(Operand(scratch, 0), result_end); | 1239 mov(Operand(scratch, 0), result_end); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 | 1451 |
| 1452 | 1452 |
| 1453 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 1453 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |
| 1454 ExternalReference new_space_allocation_top = | 1454 ExternalReference new_space_allocation_top = |
| 1455 ExternalReference::new_space_allocation_top_address(isolate()); | 1455 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1456 | 1456 |
| 1457 // Make sure the object has no tag before resetting top. | 1457 // Make sure the object has no tag before resetting top. |
| 1458 and_(object, Immediate(~kHeapObjectTagMask)); | 1458 and_(object, Immediate(~kHeapObjectTagMask)); |
| 1459 #ifdef DEBUG | 1459 #ifdef DEBUG |
| 1460 cmp(object, Operand::StaticVariable(new_space_allocation_top)); | 1460 cmp(object, Operand::StaticVariable(new_space_allocation_top)); |
| 1461 Check(below, kUndoAllocationOfNonAllocatedMemory); | 1461 Check(below, "Undo allocation of non allocated memory"); |
| 1462 #endif | 1462 #endif |
| 1463 mov(Operand::StaticVariable(new_space_allocation_top), object); | 1463 mov(Operand::StaticVariable(new_space_allocation_top), object); |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 | 1466 |
| 1467 void MacroAssembler::AllocateHeapNumber(Register result, | 1467 void MacroAssembler::AllocateHeapNumber(Register result, |
| 1468 Register scratch1, | 1468 Register scratch1, |
| 1469 Register scratch2, | 1469 Register scratch2, |
| 1470 Label* gc_required) { | 1470 Label* gc_required) { |
| 1471 // Allocate heap number in new space. | 1471 // Allocate heap number in new space. |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2055 | 2055 |
| 2056 Label promote_scheduled_exception; | 2056 Label promote_scheduled_exception; |
| 2057 Label delete_allocated_handles; | 2057 Label delete_allocated_handles; |
| 2058 Label leave_exit_frame; | 2058 Label leave_exit_frame; |
| 2059 | 2059 |
| 2060 bind(&prologue); | 2060 bind(&prologue); |
| 2061 // No more valid handles (the result handle was the last one). Restore | 2061 // No more valid handles (the result handle was the last one). Restore |
| 2062 // previous handle scope. | 2062 // previous handle scope. |
| 2063 mov(Operand::StaticVariable(next_address), ebx); | 2063 mov(Operand::StaticVariable(next_address), ebx); |
| 2064 sub(Operand::StaticVariable(level_address), Immediate(1)); | 2064 sub(Operand::StaticVariable(level_address), Immediate(1)); |
| 2065 Assert(above_equal, kInvalidHandleScopeLevel); | 2065 Assert(above_equal, "Invalid HandleScope level"); |
| 2066 cmp(edi, Operand::StaticVariable(limit_address)); | 2066 cmp(edi, Operand::StaticVariable(limit_address)); |
| 2067 j(not_equal, &delete_allocated_handles); | 2067 j(not_equal, &delete_allocated_handles); |
| 2068 bind(&leave_exit_frame); | 2068 bind(&leave_exit_frame); |
| 2069 | 2069 |
| 2070 // Check if the function scheduled an exception. | 2070 // Check if the function scheduled an exception. |
| 2071 ExternalReference scheduled_exception_address = | 2071 ExternalReference scheduled_exception_address = |
| 2072 ExternalReference::scheduled_exception_address(isolate()); | 2072 ExternalReference::scheduled_exception_address(isolate()); |
| 2073 cmp(Operand::StaticVariable(scheduled_exception_address), | 2073 cmp(Operand::StaticVariable(scheduled_exception_address), |
| 2074 Immediate(isolate()->factory()->the_hole_value())); | 2074 Immediate(isolate()->factory()->the_hole_value())); |
| 2075 j(not_equal, &promote_scheduled_exception); | 2075 j(not_equal, &promote_scheduled_exception); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2097 | 2097 |
| 2098 cmp(return_value, isolate()->factory()->true_value()); | 2098 cmp(return_value, isolate()->factory()->true_value()); |
| 2099 j(equal, &ok, Label::kNear); | 2099 j(equal, &ok, Label::kNear); |
| 2100 | 2100 |
| 2101 cmp(return_value, isolate()->factory()->false_value()); | 2101 cmp(return_value, isolate()->factory()->false_value()); |
| 2102 j(equal, &ok, Label::kNear); | 2102 j(equal, &ok, Label::kNear); |
| 2103 | 2103 |
| 2104 cmp(return_value, isolate()->factory()->null_value()); | 2104 cmp(return_value, isolate()->factory()->null_value()); |
| 2105 j(equal, &ok, Label::kNear); | 2105 j(equal, &ok, Label::kNear); |
| 2106 | 2106 |
| 2107 Abort(kAPICallReturnedInvalidObject); | 2107 Abort("API call returned invalid object"); |
| 2108 | 2108 |
| 2109 bind(&ok); | 2109 bind(&ok); |
| 2110 #endif | 2110 #endif |
| 2111 | 2111 |
| 2112 LeaveApiExitFrame(); | 2112 LeaveApiExitFrame(); |
| 2113 ret(stack_space * kPointerSize); | 2113 ret(stack_space * kPointerSize); |
| 2114 | 2114 |
| 2115 bind(&promote_scheduled_exception); | 2115 bind(&promote_scheduled_exception); |
| 2116 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 2116 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 2117 | 2117 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2383 mov(dst, esi); | 2383 mov(dst, esi); |
| 2384 } | 2384 } |
| 2385 | 2385 |
| 2386 // We should not have found a with context by walking the context chain | 2386 // We should not have found a with context by walking the context chain |
| 2387 // (i.e., the static scope chain and runtime context chain do not agree). | 2387 // (i.e., the static scope chain and runtime context chain do not agree). |
| 2388 // A variable occurring in such a scope should have slot type LOOKUP and | 2388 // A variable occurring in such a scope should have slot type LOOKUP and |
| 2389 // not CONTEXT. | 2389 // not CONTEXT. |
| 2390 if (emit_debug_code()) { | 2390 if (emit_debug_code()) { |
| 2391 cmp(FieldOperand(dst, HeapObject::kMapOffset), | 2391 cmp(FieldOperand(dst, HeapObject::kMapOffset), |
| 2392 isolate()->factory()->with_context_map()); | 2392 isolate()->factory()->with_context_map()); |
| 2393 Check(not_equal, kVariableResolvedToWithContext); | 2393 Check(not_equal, "Variable resolved to with context."); |
| 2394 } | 2394 } |
| 2395 } | 2395 } |
| 2396 | 2396 |
| 2397 | 2397 |
| 2398 void MacroAssembler::LoadTransitionedArrayMapConditional( | 2398 void MacroAssembler::LoadTransitionedArrayMapConditional( |
| 2399 ElementsKind expected_kind, | 2399 ElementsKind expected_kind, |
| 2400 ElementsKind transitioned_kind, | 2400 ElementsKind transitioned_kind, |
| 2401 Register map_in_out, | 2401 Register map_in_out, |
| 2402 Register scratch, | 2402 Register scratch, |
| 2403 Label* no_map_match) { | 2403 Label* no_map_match) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 | 2470 |
| 2471 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2471 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 2472 Register map) { | 2472 Register map) { |
| 2473 // Load the initial map. The global functions all have initial maps. | 2473 // Load the initial map. The global functions all have initial maps. |
| 2474 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2474 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2475 if (emit_debug_code()) { | 2475 if (emit_debug_code()) { |
| 2476 Label ok, fail; | 2476 Label ok, fail; |
| 2477 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); | 2477 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); |
| 2478 jmp(&ok); | 2478 jmp(&ok); |
| 2479 bind(&fail); | 2479 bind(&fail); |
| 2480 Abort(kGlobalFunctionsMustHaveInitialMap); | 2480 Abort("Global functions must have initial map"); |
| 2481 bind(&ok); | 2481 bind(&ok); |
| 2482 } | 2482 } |
| 2483 } | 2483 } |
| 2484 | 2484 |
| 2485 | 2485 |
| 2486 // Store the value in register src in the safepoint register stack | 2486 // Store the value in register src in the safepoint register stack |
| 2487 // slot for register dst. | 2487 // slot for register dst. |
| 2488 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { | 2488 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { |
| 2489 mov(SafepointRegisterSlot(dst), src); | 2489 mov(SafepointRegisterSlot(dst), src); |
| 2490 } | 2490 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2571 | 2571 |
| 2572 // The top-of-stack (tos) is 7 if there is one item pushed. | 2572 // The top-of-stack (tos) is 7 if there is one item pushed. |
| 2573 int tos = (8 - depth) % 8; | 2573 int tos = (8 - depth) % 8; |
| 2574 const int kTopMask = 0x3800; | 2574 const int kTopMask = 0x3800; |
| 2575 push(eax); | 2575 push(eax); |
| 2576 fwait(); | 2576 fwait(); |
| 2577 fnstsw_ax(); | 2577 fnstsw_ax(); |
| 2578 and_(eax, kTopMask); | 2578 and_(eax, kTopMask); |
| 2579 shr(eax, 11); | 2579 shr(eax, 11); |
| 2580 cmp(eax, Immediate(tos)); | 2580 cmp(eax, Immediate(tos)); |
| 2581 Check(equal, kUnexpectedFPUStackDepthAfterInstruction); | 2581 Check(equal, "Unexpected FPU stack depth after instruction"); |
| 2582 fnclex(); | 2582 fnclex(); |
| 2583 pop(eax); | 2583 pop(eax); |
| 2584 } | 2584 } |
| 2585 | 2585 |
| 2586 | 2586 |
| 2587 void MacroAssembler::Drop(int stack_elements) { | 2587 void MacroAssembler::Drop(int stack_elements) { |
| 2588 if (stack_elements > 0) { | 2588 if (stack_elements > 0) { |
| 2589 add(esp, Immediate(stack_elements * kPointerSize)); | 2589 add(esp, Immediate(stack_elements * kPointerSize)); |
| 2590 } | 2590 } |
| 2591 } | 2591 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2654 Label skip; | 2654 Label skip; |
| 2655 j(NegateCondition(cc), &skip); | 2655 j(NegateCondition(cc), &skip); |
| 2656 pushfd(); | 2656 pushfd(); |
| 2657 DecrementCounter(counter, value); | 2657 DecrementCounter(counter, value); |
| 2658 popfd(); | 2658 popfd(); |
| 2659 bind(&skip); | 2659 bind(&skip); |
| 2660 } | 2660 } |
| 2661 } | 2661 } |
| 2662 | 2662 |
| 2663 | 2663 |
| 2664 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 2664 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 2665 if (emit_debug_code()) Check(cc, reason); | 2665 if (emit_debug_code()) Check(cc, msg); |
| 2666 } | 2666 } |
| 2667 | 2667 |
| 2668 | 2668 |
| 2669 void MacroAssembler::AssertFastElements(Register elements) { | 2669 void MacroAssembler::AssertFastElements(Register elements) { |
| 2670 if (emit_debug_code()) { | 2670 if (emit_debug_code()) { |
| 2671 Factory* factory = isolate()->factory(); | 2671 Factory* factory = isolate()->factory(); |
| 2672 Label ok; | 2672 Label ok; |
| 2673 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 2673 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 2674 Immediate(factory->fixed_array_map())); | 2674 Immediate(factory->fixed_array_map())); |
| 2675 j(equal, &ok); | 2675 j(equal, &ok); |
| 2676 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 2676 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 2677 Immediate(factory->fixed_double_array_map())); | 2677 Immediate(factory->fixed_double_array_map())); |
| 2678 j(equal, &ok); | 2678 j(equal, &ok); |
| 2679 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 2679 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 2680 Immediate(factory->fixed_cow_array_map())); | 2680 Immediate(factory->fixed_cow_array_map())); |
| 2681 j(equal, &ok); | 2681 j(equal, &ok); |
| 2682 Abort(kJSObjectWithFastElementsMapHasSlowElements); | 2682 Abort("JSObject with fast elements map has slow elements"); |
| 2683 bind(&ok); | 2683 bind(&ok); |
| 2684 } | 2684 } |
| 2685 } | 2685 } |
| 2686 | 2686 |
| 2687 | 2687 |
| 2688 void MacroAssembler::Check(Condition cc, BailoutReason reason) { | 2688 void MacroAssembler::Check(Condition cc, const char* msg) { |
| 2689 Label L; | 2689 Label L; |
| 2690 j(cc, &L); | 2690 j(cc, &L); |
| 2691 Abort(reason); | 2691 Abort(msg); |
| 2692 // will not return here | 2692 // will not return here |
| 2693 bind(&L); | 2693 bind(&L); |
| 2694 } | 2694 } |
| 2695 | 2695 |
| 2696 | 2696 |
| 2697 void MacroAssembler::CheckStackAlignment() { | 2697 void MacroAssembler::CheckStackAlignment() { |
| 2698 int frame_alignment = OS::ActivationFrameAlignment(); | 2698 int frame_alignment = OS::ActivationFrameAlignment(); |
| 2699 int frame_alignment_mask = frame_alignment - 1; | 2699 int frame_alignment_mask = frame_alignment - 1; |
| 2700 if (frame_alignment > kPointerSize) { | 2700 if (frame_alignment > kPointerSize) { |
| 2701 ASSERT(IsPowerOf2(frame_alignment)); | 2701 ASSERT(IsPowerOf2(frame_alignment)); |
| 2702 Label alignment_as_expected; | 2702 Label alignment_as_expected; |
| 2703 test(esp, Immediate(frame_alignment_mask)); | 2703 test(esp, Immediate(frame_alignment_mask)); |
| 2704 j(zero, &alignment_as_expected); | 2704 j(zero, &alignment_as_expected); |
| 2705 // Abort if stack is not aligned. | 2705 // Abort if stack is not aligned. |
| 2706 int3(); | 2706 int3(); |
| 2707 bind(&alignment_as_expected); | 2707 bind(&alignment_as_expected); |
| 2708 } | 2708 } |
| 2709 } | 2709 } |
| 2710 | 2710 |
| 2711 | 2711 |
| 2712 void MacroAssembler::Abort(BailoutReason reason) { | 2712 void MacroAssembler::Abort(const char* msg) { |
| 2713 // We want to pass the msg string like a smi to avoid GC | 2713 // We want to pass the msg string like a smi to avoid GC |
| 2714 // problems, however msg is not guaranteed to be aligned | 2714 // problems, however msg is not guaranteed to be aligned |
| 2715 // properly. Instead, we pass an aligned pointer that is | 2715 // properly. Instead, we pass an aligned pointer that is |
| 2716 // a proper v8 smi, but also pass the alignment difference | 2716 // a proper v8 smi, but also pass the alignment difference |
| 2717 // from the real pointer as a smi. | 2717 // from the real pointer as a smi. |
| 2718 const char* msg = GetBailoutReason(reason); | |
| 2719 intptr_t p1 = reinterpret_cast<intptr_t>(msg); | 2718 intptr_t p1 = reinterpret_cast<intptr_t>(msg); |
| 2720 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; | 2719 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; |
| 2721 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); | 2720 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); |
| 2722 #ifdef DEBUG | 2721 #ifdef DEBUG |
| 2723 if (msg != NULL) { | 2722 if (msg != NULL) { |
| 2724 RecordComment("Abort message: "); | 2723 RecordComment("Abort message: "); |
| 2725 RecordComment(msg); | 2724 RecordComment(msg); |
| 2726 } | 2725 } |
| 2727 #endif | 2726 #endif |
| 2728 | 2727 |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3112 // Value is a data object, and it is white. Mark it black. Since we know | 3111 // Value is a data object, and it is white. Mark it black. Since we know |
| 3113 // that the object is white we can make it black by flipping one bit. | 3112 // that the object is white we can make it black by flipping one bit. |
| 3114 or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 3113 or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |
| 3115 | 3114 |
| 3116 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); | 3115 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); |
| 3117 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), | 3116 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), |
| 3118 length); | 3117 length); |
| 3119 if (emit_debug_code()) { | 3118 if (emit_debug_code()) { |
| 3120 mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | 3119 mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 3121 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); | 3120 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); |
| 3122 Check(less_equal, kLiveBytesCountOverflowChunkSize); | 3121 Check(less_equal, "Live Bytes Count overflow chunk size"); |
| 3123 } | 3122 } |
| 3124 | 3123 |
| 3125 bind(&done); | 3124 bind(&done); |
| 3126 } | 3125 } |
| 3127 | 3126 |
| 3128 | 3127 |
| 3129 void MacroAssembler::EnumLength(Register dst, Register map) { | 3128 void MacroAssembler::EnumLength(Register dst, Register map) { |
| 3130 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); | 3129 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); |
| 3131 mov(dst, FieldOperand(map, Map::kBitField3Offset)); | 3130 mov(dst, FieldOperand(map, Map::kBitField3Offset)); |
| 3132 and_(dst, Immediate(Smi::FromInt(Map::EnumLengthBits::kMask))); | 3131 and_(dst, Immediate(Smi::FromInt(Map::EnumLengthBits::kMask))); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3187 j(greater, &no_memento_available); | 3186 j(greater, &no_memento_available); |
| 3188 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 3187 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |
| 3189 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); | 3188 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); |
| 3190 bind(&no_memento_available); | 3189 bind(&no_memento_available); |
| 3191 } | 3190 } |
| 3192 | 3191 |
| 3193 | 3192 |
| 3194 } } // namespace v8::internal | 3193 } } // namespace v8::internal |
| 3195 | 3194 |
| 3196 #endif // V8_TARGET_ARCH_IA32 | 3195 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |