| 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 |