OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 __ fxch(1); // X - rnd(X), rnd(X) | 547 __ fxch(1); // X - rnd(X), rnd(X) |
548 // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 | 548 // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 |
549 __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) | 549 __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) |
550 __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) | 550 __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) |
551 __ faddp(1); // 2^(X-rnd(X)), rnd(X) | 551 __ faddp(1); // 2^(X-rnd(X)), rnd(X) |
552 // FSCALE calculates st(0) * 2^st(1) | 552 // FSCALE calculates st(0) * 2^st(1) |
553 __ fscale(); // 2^X, rnd(X) | 553 __ fscale(); // 2^X, rnd(X) |
554 __ fstp(1); // 2^X | 554 __ fstp(1); // 2^X |
555 // Bail out to runtime in case of exceptions in the status word. | 555 // Bail out to runtime in case of exceptions in the status word. |
556 __ fnstsw_ax(); | 556 __ fnstsw_ax(); |
557 __ test_b(eax, 0x5F); // We check for all but precision exception. | 557 __ test_b(eax, |
| 558 Immediate(0x5F)); // We check for all but precision exception. |
558 __ j(not_zero, &fast_power_failed, Label::kNear); | 559 __ j(not_zero, &fast_power_failed, Label::kNear); |
559 __ fstp_d(Operand(esp, 0)); | 560 __ fstp_d(Operand(esp, 0)); |
560 __ movsd(double_result, Operand(esp, 0)); | 561 __ movsd(double_result, Operand(esp, 0)); |
561 __ add(esp, Immediate(kDoubleSize)); | 562 __ add(esp, Immediate(kDoubleSize)); |
562 __ jmp(&done); | 563 __ jmp(&done); |
563 | 564 |
564 __ bind(&fast_power_failed); | 565 __ bind(&fast_power_failed); |
565 __ fninit(); | 566 __ fninit(); |
566 __ add(esp, Immediate(kDoubleSize)); | 567 __ add(esp, Immediate(kDoubleSize)); |
567 __ jmp(&call_runtime); | 568 __ jmp(&call_runtime); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 // (4) Cons string. Check that it's flat. | 860 // (4) Cons string. Check that it's flat. |
860 // Replace subject with first string and reload instance type. | 861 // Replace subject with first string and reload instance type. |
861 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); | 862 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); |
862 __ j(not_equal, &runtime); | 863 __ j(not_equal, &runtime); |
863 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 864 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
864 __ bind(&check_underlying); | 865 __ bind(&check_underlying); |
865 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 866 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
866 __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 867 __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
867 | 868 |
868 // (5a) Is subject sequential two byte? If yes, go to (9). | 869 // (5a) Is subject sequential two byte? If yes, go to (9). |
869 __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask); | 870 __ test_b(ebx, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
870 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 871 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
871 __ j(zero, &seq_two_byte_string); // Go to (9). | 872 __ j(zero, &seq_two_byte_string); // Go to (9). |
872 // (5b) Is subject external? If yes, go to (8). | 873 // (5b) Is subject external? If yes, go to (8). |
873 __ test_b(ebx, kStringRepresentationMask); | 874 __ test_b(ebx, Immediate(kStringRepresentationMask)); |
874 // The underlying external string is never a short external string. | 875 // The underlying external string is never a short external string. |
875 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); | 876 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); |
876 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); | 877 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); |
877 __ j(not_zero, &external_string); // Go to (8). | 878 __ j(not_zero, &external_string); // Go to (8). |
878 | 879 |
879 // eax: sequential subject string (or look-alike, external string) | 880 // eax: sequential subject string (or look-alike, external string) |
880 // edx: original subject string | 881 // edx: original subject string |
881 // ecx: RegExp data (FixedArray) | 882 // ecx: RegExp data (FixedArray) |
882 // (6) One byte sequential. Load regexp code for one byte. | 883 // (6) One byte sequential. Load regexp code for one byte. |
883 __ bind(&seq_one_byte_string); | 884 __ bind(&seq_one_byte_string); |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 1113 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
1113 | 1114 |
1114 // (8) External string. Short external strings have been ruled out. | 1115 // (8) External string. Short external strings have been ruled out. |
1115 __ bind(&external_string); | 1116 __ bind(&external_string); |
1116 // Reload instance type. | 1117 // Reload instance type. |
1117 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 1118 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
1118 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 1119 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
1119 if (FLAG_debug_code) { | 1120 if (FLAG_debug_code) { |
1120 // Assert that we do not have a cons or slice (indirect strings) here. | 1121 // Assert that we do not have a cons or slice (indirect strings) here. |
1121 // Sequential strings have already been ruled out. | 1122 // Sequential strings have already been ruled out. |
1122 __ test_b(ebx, kIsIndirectStringMask); | 1123 __ test_b(ebx, Immediate(kIsIndirectStringMask)); |
1123 __ Assert(zero, kExternalStringExpectedButNotFound); | 1124 __ Assert(zero, kExternalStringExpectedButNotFound); |
1124 } | 1125 } |
1125 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 1126 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
1126 // Move the pointer so that offset-wise, it looks like a sequential string. | 1127 // Move the pointer so that offset-wise, it looks like a sequential string. |
1127 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 1128 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
1128 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 1129 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
1129 STATIC_ASSERT(kTwoByteStringTag == 0); | 1130 STATIC_ASSERT(kTwoByteStringTag == 0); |
1130 // (8a) Is the external string one byte? If yes, go to (6). | 1131 // (8a) Is the external string one byte? If yes, go to (6). |
1131 __ test_b(ebx, kStringEncodingMask); | 1132 __ test_b(ebx, Immediate(kStringEncodingMask)); |
1132 __ j(not_zero, &seq_one_byte_string); // Goto (6). | 1133 __ j(not_zero, &seq_one_byte_string); // Goto (6). |
1133 | 1134 |
1134 // eax: sequential subject string (or look-alike, external string) | 1135 // eax: sequential subject string (or look-alike, external string) |
1135 // edx: original subject string | 1136 // edx: original subject string |
1136 // ecx: RegExp data (FixedArray) | 1137 // ecx: RegExp data (FixedArray) |
1137 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 1138 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). |
1138 __ bind(&seq_two_byte_string); | 1139 __ bind(&seq_two_byte_string); |
1139 // Load previous index and check range before edx is overwritten. We have | 1140 // Load previous index and check range before edx is overwritten. We have |
1140 // to use edx instead of eax here because it might have been only made to | 1141 // to use edx instead of eax here because it might have been only made to |
1141 // look like a sequential string when it actually is an external string. | 1142 // look like a sequential string when it actually is an external string. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 | 1247 |
1247 // Test for NaN. Compare heap numbers in a general way, | 1248 // Test for NaN. Compare heap numbers in a general way, |
1248 // to handle NaNs correctly. | 1249 // to handle NaNs correctly. |
1249 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 1250 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
1250 Immediate(isolate()->factory()->heap_number_map())); | 1251 Immediate(isolate()->factory()->heap_number_map())); |
1251 __ j(equal, &generic_heap_number_comparison, Label::kNear); | 1252 __ j(equal, &generic_heap_number_comparison, Label::kNear); |
1252 if (cc != equal) { | 1253 if (cc != equal) { |
1253 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 1254 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
1254 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 1255 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
1255 // Call runtime on identical JSObjects. Otherwise return equal. | 1256 // Call runtime on identical JSObjects. Otherwise return equal. |
1256 __ cmpb(ecx, static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE)); | 1257 __ cmpb(ecx, Immediate(FIRST_JS_RECEIVER_TYPE)); |
1257 __ j(above_equal, &runtime_call, Label::kFar); | 1258 __ j(above_equal, &runtime_call, Label::kFar); |
1258 // Call runtime on identical symbols since we need to throw a TypeError. | 1259 // Call runtime on identical symbols since we need to throw a TypeError. |
1259 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); | 1260 __ cmpb(ecx, Immediate(SYMBOL_TYPE)); |
1260 __ j(equal, &runtime_call, Label::kFar); | 1261 __ j(equal, &runtime_call, Label::kFar); |
1261 // Call runtime on identical SIMD values since we must throw a TypeError. | 1262 // Call runtime on identical SIMD values since we must throw a TypeError. |
1262 __ cmpb(ecx, static_cast<uint8_t>(SIMD128_VALUE_TYPE)); | 1263 __ cmpb(ecx, Immediate(SIMD128_VALUE_TYPE)); |
1263 __ j(equal, &runtime_call, Label::kFar); | 1264 __ j(equal, &runtime_call, Label::kFar); |
1264 } | 1265 } |
1265 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 1266 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
1266 __ ret(0); | 1267 __ ret(0); |
1267 | 1268 |
1268 | 1269 |
1269 __ bind(¬_identical); | 1270 __ bind(¬_identical); |
1270 } | 1271 } |
1271 | 1272 |
1272 // Strict equality can quickly decide whether objects are equal. | 1273 // Strict equality can quickly decide whether objects are equal. |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 STATIC_ASSERT(kSmiTag == 0); | 1413 STATIC_ASSERT(kSmiTag == 0); |
1413 STATIC_ASSERT(kSmiTagMask == 1); | 1414 STATIC_ASSERT(kSmiTagMask == 1); |
1414 __ lea(ecx, Operand(eax, edx, times_1, 0)); | 1415 __ lea(ecx, Operand(eax, edx, times_1, 0)); |
1415 __ test(ecx, Immediate(kSmiTagMask)); | 1416 __ test(ecx, Immediate(kSmiTagMask)); |
1416 __ j(not_zero, &runtime_call); | 1417 __ j(not_zero, &runtime_call); |
1417 | 1418 |
1418 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 1419 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
1419 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 1420 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
1420 | 1421 |
1421 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 1422 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
1422 1 << Map::kIsUndetectable); | 1423 Immediate(1 << Map::kIsUndetectable)); |
1423 __ j(not_zero, &undetectable, Label::kNear); | 1424 __ j(not_zero, &undetectable, Label::kNear); |
1424 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1425 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1425 1 << Map::kIsUndetectable); | 1426 Immediate(1 << Map::kIsUndetectable)); |
1426 __ j(not_zero, &return_unequal, Label::kNear); | 1427 __ j(not_zero, &return_unequal, Label::kNear); |
1427 | 1428 |
1428 __ CmpInstanceType(ebx, FIRST_JS_RECEIVER_TYPE); | 1429 __ CmpInstanceType(ebx, FIRST_JS_RECEIVER_TYPE); |
1429 __ j(below, &runtime_call, Label::kNear); | 1430 __ j(below, &runtime_call, Label::kNear); |
1430 __ CmpInstanceType(ecx, FIRST_JS_RECEIVER_TYPE); | 1431 __ CmpInstanceType(ecx, FIRST_JS_RECEIVER_TYPE); |
1431 __ j(below, &runtime_call, Label::kNear); | 1432 __ j(below, &runtime_call, Label::kNear); |
1432 | 1433 |
1433 __ bind(&return_unequal); | 1434 __ bind(&return_unequal); |
1434 // Return non-equal by returning the non-zero object pointer in eax. | 1435 // Return non-equal by returning the non-zero object pointer in eax. |
1435 __ ret(0); // eax, edx were pushed | 1436 __ ret(0); // eax, edx were pushed |
1436 | 1437 |
1437 __ bind(&undetectable); | 1438 __ bind(&undetectable); |
1438 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1439 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1439 1 << Map::kIsUndetectable); | 1440 Immediate(1 << Map::kIsUndetectable)); |
1440 __ j(zero, &return_unequal, Label::kNear); | 1441 __ j(zero, &return_unequal, Label::kNear); |
1441 | 1442 |
1442 // If both sides are JSReceivers, then the result is false according to | 1443 // If both sides are JSReceivers, then the result is false according to |
1443 // the HTML specification, which says that only comparisons with null or | 1444 // the HTML specification, which says that only comparisons with null or |
1444 // undefined are affected by special casing for document.all. | 1445 // undefined are affected by special casing for document.all. |
1445 __ CmpInstanceType(ebx, ODDBALL_TYPE); | 1446 __ CmpInstanceType(ebx, ODDBALL_TYPE); |
1446 __ j(zero, &return_equal, Label::kNear); | 1447 __ j(zero, &return_equal, Label::kNear); |
1447 __ CmpInstanceType(ecx, ODDBALL_TYPE); | 1448 __ CmpInstanceType(ecx, ODDBALL_TYPE); |
1448 __ j(not_zero, &return_unequal, Label::kNear); | 1449 __ j(not_zero, &return_unequal, Label::kNear); |
1449 | 1450 |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2132 __ ret(0); | 2133 __ ret(0); |
2133 | 2134 |
2134 // Fast-case: The {function} must be a valid JSFunction. | 2135 // Fast-case: The {function} must be a valid JSFunction. |
2135 __ bind(&fast_case); | 2136 __ bind(&fast_case); |
2136 __ JumpIfSmi(function, &slow_case); | 2137 __ JumpIfSmi(function, &slow_case); |
2137 __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); | 2138 __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); |
2138 __ j(not_equal, &slow_case); | 2139 __ j(not_equal, &slow_case); |
2139 | 2140 |
2140 // Go to the runtime if the function is not a constructor. | 2141 // Go to the runtime if the function is not a constructor. |
2141 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), | 2142 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), |
2142 static_cast<uint8_t>(1 << Map::kIsConstructor)); | 2143 Immediate(1 << Map::kIsConstructor)); |
2143 __ j(zero, &slow_case); | 2144 __ j(zero, &slow_case); |
2144 | 2145 |
2145 // Ensure that {function} has an instance prototype. | 2146 // Ensure that {function} has an instance prototype. |
2146 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), | 2147 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), |
2147 static_cast<uint8_t>(1 << Map::kHasNonInstancePrototype)); | 2148 Immediate(1 << Map::kHasNonInstancePrototype)); |
2148 __ j(not_zero, &slow_case); | 2149 __ j(not_zero, &slow_case); |
2149 | 2150 |
2150 // Get the "prototype" (or initial map) of the {function}. | 2151 // Get the "prototype" (or initial map) of the {function}. |
2151 __ mov(function_prototype, | 2152 __ mov(function_prototype, |
2152 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2153 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
2153 __ AssertNotSmi(function_prototype); | 2154 __ AssertNotSmi(function_prototype); |
2154 | 2155 |
2155 // Resolve the prototype if the {function} has an initial map. Afterwards the | 2156 // Resolve the prototype if the {function} has an initial map. Afterwards the |
2156 // {function_prototype} will be either the JSReceiver prototype object or the | 2157 // {function_prototype} will be either the JSReceiver prototype object or the |
2157 // hole value, which means that no instances of the {function} were created so | 2158 // hole value, which means that no instances of the {function} were created so |
(...skipping 13 matching lines...) Expand all Loading... |
2171 __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); | 2172 __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); |
2172 | 2173 |
2173 // Loop through the prototype chain looking for the {function} prototype. | 2174 // Loop through the prototype chain looking for the {function} prototype. |
2174 // Assume true, and change to false if not found. | 2175 // Assume true, and change to false if not found. |
2175 Label done, loop, fast_runtime_fallback; | 2176 Label done, loop, fast_runtime_fallback; |
2176 __ mov(eax, isolate()->factory()->true_value()); | 2177 __ mov(eax, isolate()->factory()->true_value()); |
2177 __ bind(&loop); | 2178 __ bind(&loop); |
2178 | 2179 |
2179 // Check if the object needs to be access checked. | 2180 // Check if the object needs to be access checked. |
2180 __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), | 2181 __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), |
2181 1 << Map::kIsAccessCheckNeeded); | 2182 Immediate(1 << Map::kIsAccessCheckNeeded)); |
2182 __ j(not_zero, &fast_runtime_fallback, Label::kNear); | 2183 __ j(not_zero, &fast_runtime_fallback, Label::kNear); |
2183 // Check if the current object is a Proxy. | 2184 // Check if the current object is a Proxy. |
2184 __ CmpInstanceType(object_map, JS_PROXY_TYPE); | 2185 __ CmpInstanceType(object_map, JS_PROXY_TYPE); |
2185 __ j(equal, &fast_runtime_fallback, Label::kNear); | 2186 __ j(equal, &fast_runtime_fallback, Label::kNear); |
2186 | 2187 |
2187 __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset)); | 2188 __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset)); |
2188 __ cmp(object, function_prototype); | 2189 __ cmp(object, function_prototype); |
2189 __ j(equal, &done, Label::kNear); | 2190 __ j(equal, &done, Label::kNear); |
2190 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); | 2191 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); |
2191 __ cmp(object, isolate()->factory()->null_value()); | 2192 __ cmp(object, isolate()->factory()->null_value()); |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2518 | 2519 |
2519 // edi: underlying subject string | 2520 // edi: underlying subject string |
2520 // ebx: instance type of underlying subject string | 2521 // ebx: instance type of underlying subject string |
2521 // edx: adjusted start index (smi) | 2522 // edx: adjusted start index (smi) |
2522 // ecx: length (smi) | 2523 // ecx: length (smi) |
2523 // The subject string can only be external or sequential string of either | 2524 // The subject string can only be external or sequential string of either |
2524 // encoding at this point. | 2525 // encoding at this point. |
2525 Label two_byte_sequential, runtime_drop_two, sequential_string; | 2526 Label two_byte_sequential, runtime_drop_two, sequential_string; |
2526 STATIC_ASSERT(kExternalStringTag != 0); | 2527 STATIC_ASSERT(kExternalStringTag != 0); |
2527 STATIC_ASSERT(kSeqStringTag == 0); | 2528 STATIC_ASSERT(kSeqStringTag == 0); |
2528 __ test_b(ebx, kExternalStringTag); | 2529 __ test_b(ebx, Immediate(kExternalStringTag)); |
2529 __ j(zero, &sequential_string); | 2530 __ j(zero, &sequential_string); |
2530 | 2531 |
2531 // Handle external string. | 2532 // Handle external string. |
2532 // Rule out short external strings. | 2533 // Rule out short external strings. |
2533 STATIC_ASSERT(kShortExternalStringTag != 0); | 2534 STATIC_ASSERT(kShortExternalStringTag != 0); |
2534 __ test_b(ebx, kShortExternalStringMask); | 2535 __ test_b(ebx, Immediate(kShortExternalStringMask)); |
2535 __ j(not_zero, &runtime); | 2536 __ j(not_zero, &runtime); |
2536 __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); | 2537 __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); |
2537 // Move the pointer so that offset-wise, it looks like a sequential string. | 2538 // Move the pointer so that offset-wise, it looks like a sequential string. |
2538 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 2539 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
2539 __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 2540 __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
2540 | 2541 |
2541 __ bind(&sequential_string); | 2542 __ bind(&sequential_string); |
2542 // Stash away (adjusted) index and (underlying) string. | 2543 // Stash away (adjusted) index and (underlying) string. |
2543 __ push(edx); | 2544 __ push(edx); |
2544 __ push(edi); | 2545 __ push(edi); |
2545 __ SmiUntag(ecx); | 2546 __ SmiUntag(ecx); |
2546 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 2547 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
2547 __ test_b(ebx, kStringEncodingMask); | 2548 __ test_b(ebx, Immediate(kStringEncodingMask)); |
2548 __ j(zero, &two_byte_sequential); | 2549 __ j(zero, &two_byte_sequential); |
2549 | 2550 |
2550 // Sequential one byte string. Allocate the result. | 2551 // Sequential one byte string. Allocate the result. |
2551 __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 2552 __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); |
2552 | 2553 |
2553 // eax: result string | 2554 // eax: result string |
2554 // ecx: result string length | 2555 // ecx: result string length |
2555 // Locate first character of result. | 2556 // Locate first character of result. |
2556 __ mov(edi, eax); | 2557 __ mov(edi, eax); |
2557 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 2558 __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
(...skipping 1879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4437 Label normal_sequence; | 4438 Label normal_sequence; |
4438 if (mode == DONT_OVERRIDE) { | 4439 if (mode == DONT_OVERRIDE) { |
4439 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | 4440 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
4440 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 4441 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
4441 STATIC_ASSERT(FAST_ELEMENTS == 2); | 4442 STATIC_ASSERT(FAST_ELEMENTS == 2); |
4442 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | 4443 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); |
4443 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 4444 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
4444 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 4445 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
4445 | 4446 |
4446 // is the low bit set? If so, we are holey and that is good. | 4447 // is the low bit set? If so, we are holey and that is good. |
4447 __ test_b(edx, 1); | 4448 __ test_b(edx, Immediate(1)); |
4448 __ j(not_zero, &normal_sequence); | 4449 __ j(not_zero, &normal_sequence); |
4449 } | 4450 } |
4450 | 4451 |
4451 // look at the first argument | 4452 // look at the first argument |
4452 __ mov(ecx, Operand(esp, kPointerSize)); | 4453 __ mov(ecx, Operand(esp, kPointerSize)); |
4453 __ test(ecx, ecx); | 4454 __ test(ecx, ecx); |
4454 __ j(zero, &normal_sequence); | 4455 __ j(zero, &normal_sequence); |
4455 | 4456 |
4456 if (mode == DISABLE_ALLOCATION_SITES) { | 4457 if (mode == DISABLE_ALLOCATION_SITES) { |
4457 ElementsKind initial = GetInitialFastElementsKind(); | 4458 ElementsKind initial = GetInitialFastElementsKind(); |
(...skipping 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5581 Immediate(ExternalReference::isolate_address(isolate))); | 5582 Immediate(ExternalReference::isolate_address(isolate))); |
5582 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), | 5583 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
5583 1); | 5584 1); |
5584 __ PopSafepointRegisters(); | 5585 __ PopSafepointRegisters(); |
5585 } | 5586 } |
5586 | 5587 |
5587 | 5588 |
5588 Label profiler_disabled; | 5589 Label profiler_disabled; |
5589 Label end_profiler_check; | 5590 Label end_profiler_check; |
5590 __ mov(eax, Immediate(ExternalReference::is_profiling_address(isolate))); | 5591 __ mov(eax, Immediate(ExternalReference::is_profiling_address(isolate))); |
5591 __ cmpb(Operand(eax, 0), 0); | 5592 __ cmpb(Operand(eax, 0), Immediate(0)); |
5592 __ j(zero, &profiler_disabled); | 5593 __ j(zero, &profiler_disabled); |
5593 | 5594 |
5594 // Additional parameter is the address of the actual getter function. | 5595 // Additional parameter is the address of the actual getter function. |
5595 __ mov(thunk_last_arg, function_address); | 5596 __ mov(thunk_last_arg, function_address); |
5596 // Call the api function. | 5597 // Call the api function. |
5597 __ mov(eax, Immediate(thunk_ref)); | 5598 __ mov(eax, Immediate(thunk_ref)); |
5598 __ call(eax); | 5599 __ call(eax); |
5599 __ jmp(&end_profiler_check); | 5600 __ jmp(&end_profiler_check); |
5600 | 5601 |
5601 __ bind(&profiler_disabled); | 5602 __ bind(&profiler_disabled); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5880 return_value_operand, NULL); | 5881 return_value_operand, NULL); |
5881 } | 5882 } |
5882 | 5883 |
5883 | 5884 |
5884 #undef __ | 5885 #undef __ |
5885 | 5886 |
5886 } // namespace internal | 5887 } // namespace internal |
5887 } // namespace v8 | 5888 } // namespace v8 |
5888 | 5889 |
5889 #endif // V8_TARGET_ARCH_IA32 | 5890 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |