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