OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1897 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1897 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
1898 | 1898 |
1899 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1899 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1900 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1900 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1901 | 1901 |
1902 // Replace function on TOS with result in rax, or pop it. | 1902 // Replace function on TOS with result in rax, or pop it. |
1903 DropAndApply(1, context_, rax); | 1903 DropAndApply(1, context_, rax); |
1904 } | 1904 } |
1905 | 1905 |
1906 | 1906 |
1907 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | |
1908 Handle<String> name = expr->name(); | |
1909 if (strcmp("_IsSmi", *name->ToCString()) == 0) { | |
1910 EmitIsSmi(expr->arguments()); | |
1911 } else if (strcmp("_IsNonNegativeSmi", *name->ToCString()) == 0) { | |
1912 EmitIsNonNegativeSmi(expr->arguments()); | |
1913 } else if (strcmp("_IsObject", *name->ToCString()) == 0) { | |
1914 EmitIsObject(expr->arguments()); | |
1915 } else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) { | |
1916 EmitIsUndetectableObject(expr->arguments()); | |
1917 } else if (strcmp("_IsFunction", *name->ToCString()) == 0) { | |
1918 EmitIsFunction(expr->arguments()); | |
1919 } else if (strcmp("_IsArray", *name->ToCString()) == 0) { | |
1920 EmitIsArray(expr->arguments()); | |
1921 } else if (strcmp("_IsRegExp", *name->ToCString()) == 0) { | |
1922 EmitIsRegExp(expr->arguments()); | |
1923 } else if (strcmp("_IsConstructCall", *name->ToCString()) == 0) { | |
1924 EmitIsConstructCall(expr->arguments()); | |
1925 } else if (strcmp("_ObjectEquals", *name->ToCString()) == 0) { | |
1926 EmitObjectEquals(expr->arguments()); | |
1927 } else if (strcmp("_Arguments", *name->ToCString()) == 0) { | |
1928 EmitArguments(expr->arguments()); | |
1929 } else if (strcmp("_ArgumentsLength", *name->ToCString()) == 0) { | |
1930 EmitArgumentsLength(expr->arguments()); | |
1931 } else if (strcmp("_ClassOf", *name->ToCString()) == 0) { | |
1932 EmitClassOf(expr->arguments()); | |
1933 } else if (strcmp("_Log", *name->ToCString()) == 0) { | |
1934 EmitLog(expr->arguments()); | |
1935 } else if (strcmp("_RandomHeapNumber", *name->ToCString()) == 0) { | |
1936 EmitRandomHeapNumber(expr->arguments()); | |
1937 } else if (strcmp("_SubString", *name->ToCString()) == 0) { | |
1938 EmitSubString(expr->arguments()); | |
1939 } else if (strcmp("_RegExpExec", *name->ToCString()) == 0) { | |
1940 EmitRegExpExec(expr->arguments()); | |
1941 } else if (strcmp("_ValueOf", *name->ToCString()) == 0) { | |
1942 EmitValueOf(expr->arguments()); | |
1943 } else if (strcmp("_SetValueOf", *name->ToCString()) == 0) { | |
1944 EmitSetValueOf(expr->arguments()); | |
1945 } else if (strcmp("_NumberToString", *name->ToCString()) == 0) { | |
1946 EmitNumberToString(expr->arguments()); | |
1947 } else if (strcmp("_CharFromCode", *name->ToCString()) == 0) { | |
1948 EmitCharFromCode(expr->arguments()); | |
1949 } else if (strcmp("_FastCharCodeAt", *name->ToCString()) == 0) { | |
1950 EmitFastCharCodeAt(expr->arguments()); | |
1951 } else if (strcmp("_StringAdd", *name->ToCString()) == 0) { | |
1952 EmitStringAdd(expr->arguments()); | |
1953 } else if (strcmp("_StringCompare", *name->ToCString()) == 0) { | |
1954 EmitStringCompare(expr->arguments()); | |
1955 } else if (strcmp("_MathPow", *name->ToCString()) == 0) { | |
1956 EmitMathPow(expr->arguments()); | |
1957 } else if (strcmp("_MathSin", *name->ToCString()) == 0) { | |
1958 EmitMathSin(expr->arguments()); | |
1959 } else if (strcmp("_MathCos", *name->ToCString()) == 0) { | |
1960 EmitMathCos(expr->arguments()); | |
1961 } else if (strcmp("_MathSqrt", *name->ToCString()) == 0) { | |
1962 EmitMathSqrt(expr->arguments()); | |
1963 } else if (strcmp("_CallFunction", *name->ToCString()) == 0) { | |
1964 EmitCallFunction(expr->arguments()); | |
1965 } else if (strcmp("_RegExpConstructResult", *name->ToCString()) == 0) { | |
1966 EmitRegExpConstructResult(expr->arguments()); | |
1967 } else if (strcmp("_SwapElements", *name->ToCString()) == 0) { | |
1968 EmitSwapElements(expr->arguments()); | |
1969 } else if (strcmp("_GetFromCache", *name->ToCString()) == 0) { | |
1970 EmitGetFromCache(expr->arguments()); | |
1971 } else { | |
1972 UNREACHABLE(); | |
1973 } | |
1974 } | |
1975 | |
1976 | |
1977 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 1907 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
1978 ASSERT(args->length() == 1); | 1908 ASSERT(args->length() == 1); |
1979 | 1909 |
1980 VisitForValue(args->at(0), kAccumulator); | 1910 VisitForValue(args->at(0), kAccumulator); |
1981 | 1911 |
1982 Label materialize_true, materialize_false; | 1912 Label materialize_true, materialize_false; |
1983 Label* if_true = NULL; | 1913 Label* if_true = NULL; |
1984 Label* if_false = NULL; | 1914 Label* if_false = NULL; |
1985 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1915 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1986 | 1916 |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2405 | 2335 |
2406 // Load the argument on the stack and call the stub. | 2336 // Load the argument on the stack and call the stub. |
2407 VisitForValue(args->at(0), kStack); | 2337 VisitForValue(args->at(0), kStack); |
2408 | 2338 |
2409 NumberToStringStub stub; | 2339 NumberToStringStub stub; |
2410 __ CallStub(&stub); | 2340 __ CallStub(&stub); |
2411 Apply(context_, rax); | 2341 Apply(context_, rax); |
2412 } | 2342 } |
2413 | 2343 |
2414 | 2344 |
2415 void FullCodeGenerator::EmitCharFromCode(ZoneList<Expression*>* args) { | 2345 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
2416 ASSERT(args->length() == 1); | 2346 ASSERT(args->length() == 1); |
2417 | 2347 |
2418 VisitForValue(args->at(0), kAccumulator); | 2348 VisitForValue(args->at(0), kAccumulator); |
2419 | 2349 |
2420 Label slow_case, done; | 2350 Label done; |
2421 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 2351 StringCharFromCodeGenerator generator(rax, rbx); |
2422 __ JumpIfNotSmi(rax, &slow_case); | 2352 generator.GenerateFast(masm_); |
2423 __ SmiToInteger32(rcx, rax); | |
2424 __ cmpl(rcx, Immediate(String::kMaxAsciiCharCode)); | |
2425 __ j(above, &slow_case); | |
2426 | |
2427 __ Move(rbx, Factory::single_character_string_cache()); | |
2428 __ movq(rbx, FieldOperand(rbx, | |
2429 rcx, | |
2430 times_pointer_size, | |
2431 FixedArray::kHeaderSize)); | |
2432 | |
2433 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | |
2434 __ j(equal, &slow_case); | |
2435 __ movq(rax, rbx); | |
2436 __ jmp(&done); | 2353 __ jmp(&done); |
2437 | 2354 |
2438 __ bind(&slow_case); | 2355 NopRuntimeCallHelper call_helper; |
2439 __ push(rax); | 2356 generator.GenerateSlow(masm_, call_helper); |
2440 __ CallRuntime(Runtime::kCharFromCode, 1); | |
2441 | 2357 |
2442 __ bind(&done); | 2358 __ bind(&done); |
2443 Apply(context_, rax); | 2359 Apply(context_, rbx); |
2444 } | 2360 } |
2445 | 2361 |
2446 | 2362 |
2447 void FullCodeGenerator::EmitFastCharCodeAt(ZoneList<Expression*>* args) { | 2363 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { |
2448 // TODO(fsc): Port the complete implementation from the classic back-end. | 2364 ASSERT(args->length() == 2); |
| 2365 |
| 2366 VisitForValue(args->at(0), kStack); |
| 2367 VisitForValue(args->at(1), kAccumulator); |
| 2368 |
| 2369 Register object = rbx; |
| 2370 Register index = rax; |
| 2371 Register scratch = rcx; |
| 2372 Register result = rdx; |
| 2373 |
| 2374 __ pop(object); |
| 2375 |
| 2376 Label need_conversion; |
| 2377 Label index_out_of_range; |
| 2378 Label done; |
| 2379 StringCharCodeAtGenerator generator(object, |
| 2380 index, |
| 2381 scratch, |
| 2382 result, |
| 2383 &need_conversion, |
| 2384 &need_conversion, |
| 2385 &index_out_of_range, |
| 2386 STRING_ANY_NUMBER_INDEX); |
| 2387 generator.GenerateFast(masm_); |
| 2388 __ jmp(&done); |
| 2389 |
| 2390 __ bind(&index_out_of_range); |
| 2391 // When the index is out of range, the spec requires us to return |
| 2392 // NaN. |
| 2393 __ LoadRoot(result, Heap::kNanValueRootIndex); |
| 2394 __ jmp(&done); |
| 2395 |
| 2396 __ bind(&need_conversion); |
2449 // Move the undefined value into the result register, which will | 2397 // Move the undefined value into the result register, which will |
2450 // trigger the slow case. | 2398 // trigger conversion. |
2451 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2399 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
2452 Apply(context_, rax); | 2400 __ jmp(&done); |
| 2401 |
| 2402 NopRuntimeCallHelper call_helper; |
| 2403 generator.GenerateSlow(masm_, call_helper); |
| 2404 |
| 2405 __ bind(&done); |
| 2406 Apply(context_, result); |
2453 } | 2407 } |
2454 | 2408 |
| 2409 |
| 2410 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { |
| 2411 ASSERT(args->length() == 2); |
| 2412 |
| 2413 VisitForValue(args->at(0), kStack); |
| 2414 VisitForValue(args->at(1), kAccumulator); |
| 2415 |
| 2416 Register object = rbx; |
| 2417 Register index = rax; |
| 2418 Register scratch1 = rcx; |
| 2419 Register scratch2 = rdx; |
| 2420 Register result = rax; |
| 2421 |
| 2422 __ pop(object); |
| 2423 |
| 2424 Label need_conversion; |
| 2425 Label index_out_of_range; |
| 2426 Label done; |
| 2427 StringCharAtGenerator generator(object, |
| 2428 index, |
| 2429 scratch1, |
| 2430 scratch2, |
| 2431 result, |
| 2432 &need_conversion, |
| 2433 &need_conversion, |
| 2434 &index_out_of_range, |
| 2435 STRING_ANY_NUMBER_INDEX); |
| 2436 generator.GenerateFast(masm_); |
| 2437 __ jmp(&done); |
| 2438 |
| 2439 __ bind(&index_out_of_range); |
| 2440 // When the index is out of range, the spec requires us to return |
| 2441 // the empty string. |
| 2442 __ LoadRoot(result, Heap::kEmptyStringRootIndex); |
| 2443 __ jmp(&done); |
| 2444 |
| 2445 __ bind(&need_conversion); |
| 2446 // Move smi zero into the result register, which will trigger |
| 2447 // conversion. |
| 2448 __ Move(result, Smi::FromInt(0)); |
| 2449 __ jmp(&done); |
| 2450 |
| 2451 NopRuntimeCallHelper call_helper; |
| 2452 generator.GenerateSlow(masm_, call_helper); |
| 2453 |
| 2454 __ bind(&done); |
| 2455 Apply(context_, result); |
| 2456 } |
| 2457 |
| 2458 |
2455 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 2459 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
2456 ASSERT_EQ(2, args->length()); | 2460 ASSERT_EQ(2, args->length()); |
2457 | 2461 |
2458 VisitForValue(args->at(0), kStack); | 2462 VisitForValue(args->at(0), kStack); |
2459 VisitForValue(args->at(1), kStack); | 2463 VisitForValue(args->at(1), kStack); |
2460 | 2464 |
2461 StringAddStub stub(NO_STRING_ADD_FLAGS); | 2465 StringAddStub stub(NO_STRING_ADD_FLAGS); |
2462 __ CallStub(&stub); | 2466 __ CallStub(&stub); |
2463 Apply(context_, rax); | 2467 Apply(context_, rax); |
2464 } | 2468 } |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3210 __ ret(0); | 3214 __ ret(0); |
3211 } | 3215 } |
3212 | 3216 |
3213 | 3217 |
3214 #undef __ | 3218 #undef __ |
3215 | 3219 |
3216 | 3220 |
3217 } } // namespace v8::internal | 3221 } } // namespace v8::internal |
3218 | 3222 |
3219 #endif // V8_TARGET_ARCH_X64 | 3223 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |