OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1820 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
1821 | 1821 |
1822 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1822 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1823 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1823 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1824 | 1824 |
1825 // Replace function on TOS with result in r0, or pop it. | 1825 // Replace function on TOS with result in r0, or pop it. |
1826 DropAndApply(1, context_, r0); | 1826 DropAndApply(1, context_, r0); |
1827 } | 1827 } |
1828 | 1828 |
1829 | 1829 |
1830 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | |
1831 Handle<String> name = expr->name(); | |
1832 if (strcmp("_IsSmi", *name->ToCString()) == 0) { | |
1833 EmitIsSmi(expr->arguments()); | |
1834 } else if (strcmp("_IsNonNegativeSmi", *name->ToCString()) == 0) { | |
1835 EmitIsNonNegativeSmi(expr->arguments()); | |
1836 } else if (strcmp("_IsObject", *name->ToCString()) == 0) { | |
1837 EmitIsObject(expr->arguments()); | |
1838 } else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) { | |
1839 EmitIsUndetectableObject(expr->arguments()); | |
1840 } else if (strcmp("_IsFunction", *name->ToCString()) == 0) { | |
1841 EmitIsFunction(expr->arguments()); | |
1842 } else if (strcmp("_IsArray", *name->ToCString()) == 0) { | |
1843 EmitIsArray(expr->arguments()); | |
1844 } else if (strcmp("_IsRegExp", *name->ToCString()) == 0) { | |
1845 EmitIsRegExp(expr->arguments()); | |
1846 } else if (strcmp("_IsConstructCall", *name->ToCString()) == 0) { | |
1847 EmitIsConstructCall(expr->arguments()); | |
1848 } else if (strcmp("_ObjectEquals", *name->ToCString()) == 0) { | |
1849 EmitObjectEquals(expr->arguments()); | |
1850 } else if (strcmp("_Arguments", *name->ToCString()) == 0) { | |
1851 EmitArguments(expr->arguments()); | |
1852 } else if (strcmp("_ArgumentsLength", *name->ToCString()) == 0) { | |
1853 EmitArgumentsLength(expr->arguments()); | |
1854 } else if (strcmp("_ClassOf", *name->ToCString()) == 0) { | |
1855 EmitClassOf(expr->arguments()); | |
1856 } else if (strcmp("_Log", *name->ToCString()) == 0) { | |
1857 EmitLog(expr->arguments()); | |
1858 } else if (strcmp("_RandomHeapNumber", *name->ToCString()) == 0) { | |
1859 EmitRandomHeapNumber(expr->arguments()); | |
1860 } else if (strcmp("_SubString", *name->ToCString()) == 0) { | |
1861 EmitSubString(expr->arguments()); | |
1862 } else if (strcmp("_RegExpExec", *name->ToCString()) == 0) { | |
1863 EmitRegExpExec(expr->arguments()); | |
1864 } else if (strcmp("_ValueOf", *name->ToCString()) == 0) { | |
1865 EmitValueOf(expr->arguments()); | |
1866 } else if (strcmp("_SetValueOf", *name->ToCString()) == 0) { | |
1867 EmitSetValueOf(expr->arguments()); | |
1868 } else if (strcmp("_NumberToString", *name->ToCString()) == 0) { | |
1869 EmitNumberToString(expr->arguments()); | |
1870 } else if (strcmp("_CharFromCode", *name->ToCString()) == 0) { | |
1871 EmitCharFromCode(expr->arguments()); | |
1872 } else if (strcmp("_FastCharCodeAt", *name->ToCString()) == 0) { | |
1873 EmitFastCharCodeAt(expr->arguments()); | |
1874 } else if (strcmp("_StringAdd", *name->ToCString()) == 0) { | |
1875 EmitStringAdd(expr->arguments()); | |
1876 } else if (strcmp("_StringCompare", *name->ToCString()) == 0) { | |
1877 EmitStringCompare(expr->arguments()); | |
1878 } else if (strcmp("_MathPow", *name->ToCString()) == 0) { | |
1879 EmitMathPow(expr->arguments()); | |
1880 } else if (strcmp("_MathSin", *name->ToCString()) == 0) { | |
1881 EmitMathSin(expr->arguments()); | |
1882 } else if (strcmp("_MathCos", *name->ToCString()) == 0) { | |
1883 EmitMathCos(expr->arguments()); | |
1884 } else if (strcmp("_MathSqrt", *name->ToCString()) == 0) { | |
1885 EmitMathSqrt(expr->arguments()); | |
1886 } else if (strcmp("_CallFunction", *name->ToCString()) == 0) { | |
1887 EmitCallFunction(expr->arguments()); | |
1888 } else if (strcmp("_RegExpConstructResult", *name->ToCString()) == 0) { | |
1889 EmitRegExpConstructResult(expr->arguments()); | |
1890 } else if (strcmp("_SwapElements", *name->ToCString()) == 0) { | |
1891 EmitSwapElements(expr->arguments()); | |
1892 } else if (strcmp("_GetFromCache", *name->ToCString()) == 0) { | |
1893 EmitGetFromCache(expr->arguments()); | |
1894 } else { | |
1895 UNREACHABLE(); | |
1896 } | |
1897 } | |
1898 | |
1899 | |
1900 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 1830 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
1901 ASSERT(args->length() == 1); | 1831 ASSERT(args->length() == 1); |
1902 | 1832 |
1903 VisitForValue(args->at(0), kAccumulator); | 1833 VisitForValue(args->at(0), kAccumulator); |
1904 | 1834 |
1905 Label materialize_true, materialize_false; | 1835 Label materialize_true, materialize_false; |
1906 Label* if_true = NULL; | 1836 Label* if_true = NULL; |
1907 Label* if_false = NULL; | 1837 Label* if_false = NULL; |
1908 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1838 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1909 | 1839 |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 | 2270 |
2341 // Load the argument on the stack and call the stub. | 2271 // Load the argument on the stack and call the stub. |
2342 VisitForValue(args->at(0), kStack); | 2272 VisitForValue(args->at(0), kStack); |
2343 | 2273 |
2344 NumberToStringStub stub; | 2274 NumberToStringStub stub; |
2345 __ CallStub(&stub); | 2275 __ CallStub(&stub); |
2346 Apply(context_, r0); | 2276 Apply(context_, r0); |
2347 } | 2277 } |
2348 | 2278 |
2349 | 2279 |
2350 void FullCodeGenerator::EmitCharFromCode(ZoneList<Expression*>* args) { | 2280 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
2351 ASSERT(args->length() == 1); | 2281 ASSERT(args->length() == 1); |
2352 | 2282 |
2353 VisitForValue(args->at(0), kAccumulator); | 2283 VisitForValue(args->at(0), kAccumulator); |
2354 | 2284 |
2355 Label slow_case, done; | 2285 Label done; |
2356 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 2286 StringCharFromCodeGenerator generator(r0, r1); |
2357 ASSERT(kSmiTag == 0); | 2287 generator.GenerateFast(masm_); |
2358 ASSERT(kSmiShiftSize == 0); | 2288 __ jmp(&done); |
2359 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); | |
2360 __ tst(r0, Operand(kSmiTagMask | | |
2361 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | |
2362 __ b(nz, &slow_case); | |
2363 __ mov(r1, Operand(Factory::single_character_string_cache())); | |
2364 ASSERT(kSmiTag == 0); | |
2365 ASSERT(kSmiTagSize == 1); | |
2366 ASSERT(kSmiShiftSize == 0); | |
2367 // At this point code register contains smi tagged ascii char code. | |
2368 __ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
2369 __ ldr(r1, MemOperand(r1, FixedArray::kHeaderSize - kHeapObjectTag)); | |
2370 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | |
2371 __ cmp(r1, r2); | |
2372 __ b(eq, &slow_case); | |
2373 __ mov(r0, r1); | |
2374 __ b(&done); | |
2375 | 2289 |
2376 __ bind(&slow_case); | 2290 NopRuntimeCallHelper call_helper; |
2377 __ push(r0); | 2291 generator.GenerateSlow(masm_, call_helper); |
2378 __ CallRuntime(Runtime::kCharFromCode, 1); | |
2379 | 2292 |
2380 __ bind(&done); | 2293 __ bind(&done); |
2381 Apply(context_, r0); | 2294 Apply(context_, r1); |
2382 } | 2295 } |
2383 | 2296 |
2384 | 2297 |
2385 void FullCodeGenerator::EmitFastCharCodeAt(ZoneList<Expression*>* args) { | 2298 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { |
2386 // TODO(fsc): Port the complete implementation from the classic back-end. | 2299 ASSERT(args->length() == 2); |
2387 // Move the undefined value into the result register, which will | 2300 |
2388 // trigger the slow case. | 2301 VisitForValue(args->at(0), kStack); |
2389 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2302 VisitForValue(args->at(1), kAccumulator); |
2390 Apply(context_, r0); | 2303 |
| 2304 Register object = r1; |
| 2305 Register index = r0; |
| 2306 Register scratch = r2; |
| 2307 Register result = r3; |
| 2308 |
| 2309 __ pop(object); |
| 2310 |
| 2311 Label need_conversion; |
| 2312 Label index_out_of_range; |
| 2313 Label done; |
| 2314 StringCharCodeAtGenerator generator(object, |
| 2315 index, |
| 2316 scratch, |
| 2317 result, |
| 2318 &need_conversion, |
| 2319 &need_conversion, |
| 2320 &index_out_of_range, |
| 2321 STRING_ANY_NUMBER_INDEX); |
| 2322 generator.GenerateFast(masm_); |
| 2323 __ jmp(&done); |
| 2324 |
| 2325 __ bind(&index_out_of_range); |
| 2326 // When the index is out of range, the spec requires us to return |
| 2327 // NaN. |
| 2328 __ LoadRoot(result, Heap::kNanValueRootIndex); |
| 2329 __ jmp(&done); |
| 2330 |
| 2331 __ bind(&need_conversion); |
| 2332 // Load the undefined value into the result register, which will |
| 2333 // trigger conversion. |
| 2334 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 2335 __ jmp(&done); |
| 2336 |
| 2337 NopRuntimeCallHelper call_helper; |
| 2338 generator.GenerateSlow(masm_, call_helper); |
| 2339 |
| 2340 __ bind(&done); |
| 2341 Apply(context_, result); |
2391 } | 2342 } |
2392 | 2343 |
| 2344 |
| 2345 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { |
| 2346 ASSERT(args->length() == 2); |
| 2347 |
| 2348 VisitForValue(args->at(0), kStack); |
| 2349 VisitForValue(args->at(1), kAccumulator); |
| 2350 |
| 2351 Register object = r1; |
| 2352 Register index = r0; |
| 2353 Register scratch1 = r2; |
| 2354 Register scratch2 = r3; |
| 2355 Register result = r0; |
| 2356 |
| 2357 __ pop(object); |
| 2358 |
| 2359 Label need_conversion; |
| 2360 Label index_out_of_range; |
| 2361 Label done; |
| 2362 StringCharAtGenerator generator(object, |
| 2363 index, |
| 2364 scratch1, |
| 2365 scratch2, |
| 2366 result, |
| 2367 &need_conversion, |
| 2368 &need_conversion, |
| 2369 &index_out_of_range, |
| 2370 STRING_ANY_NUMBER_INDEX); |
| 2371 generator.GenerateFast(masm_); |
| 2372 __ jmp(&done); |
| 2373 |
| 2374 __ bind(&index_out_of_range); |
| 2375 // When the index is out of range, the spec requires us to return |
| 2376 // the empty string. |
| 2377 __ LoadRoot(result, Heap::kEmptyStringRootIndex); |
| 2378 __ jmp(&done); |
| 2379 |
| 2380 __ bind(&need_conversion); |
| 2381 // Move smi zero into the result register, which will trigger |
| 2382 // conversion. |
| 2383 __ mov(result, Operand(Smi::FromInt(0))); |
| 2384 __ jmp(&done); |
| 2385 |
| 2386 NopRuntimeCallHelper call_helper; |
| 2387 generator.GenerateSlow(masm_, call_helper); |
| 2388 |
| 2389 __ bind(&done); |
| 2390 Apply(context_, result); |
| 2391 } |
| 2392 |
| 2393 |
2393 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 2394 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
2394 ASSERT_EQ(2, args->length()); | 2395 ASSERT_EQ(2, args->length()); |
2395 | 2396 |
2396 VisitForValue(args->at(0), kStack); | 2397 VisitForValue(args->at(0), kStack); |
2397 VisitForValue(args->at(1), kStack); | 2398 VisitForValue(args->at(1), kStack); |
2398 | 2399 |
2399 StringAddStub stub(NO_STRING_ADD_FLAGS); | 2400 StringAddStub stub(NO_STRING_ADD_FLAGS); |
2400 __ CallStub(&stub); | 2401 __ CallStub(&stub); |
2401 Apply(context_, r0); | 2402 Apply(context_, r0); |
2402 } | 2403 } |
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3132 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3133 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3133 __ add(pc, r1, Operand(masm_->CodeObject())); | 3134 __ add(pc, r1, Operand(masm_->CodeObject())); |
3134 } | 3135 } |
3135 | 3136 |
3136 | 3137 |
3137 #undef __ | 3138 #undef __ |
3138 | 3139 |
3139 } } // namespace v8::internal | 3140 } } // namespace v8::internal |
3140 | 3141 |
3141 #endif // V8_TARGET_ARCH_ARM | 3142 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |