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 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1895 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1896 | 1896 |
1897 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1897 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1898 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1898 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1899 | 1899 |
1900 // Replace function on TOS with result in eax, or pop it. | 1900 // Replace function on TOS with result in eax, or pop it. |
1901 DropAndApply(1, context_, eax); | 1901 DropAndApply(1, context_, eax); |
1902 } | 1902 } |
1903 | 1903 |
1904 | 1904 |
1905 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | |
1906 Handle<String> name = expr->name(); | |
1907 if (strcmp("_IsSmi", *name->ToCString()) == 0) { | |
1908 EmitIsSmi(expr->arguments()); | |
1909 } else if (strcmp("_IsNonNegativeSmi", *name->ToCString()) == 0) { | |
1910 EmitIsNonNegativeSmi(expr->arguments()); | |
1911 } else if (strcmp("_IsObject", *name->ToCString()) == 0) { | |
1912 EmitIsObject(expr->arguments()); | |
1913 } else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) { | |
1914 EmitIsUndetectableObject(expr->arguments()); | |
1915 } else if (strcmp("_IsFunction", *name->ToCString()) == 0) { | |
1916 EmitIsFunction(expr->arguments()); | |
1917 } else if (strcmp("_IsArray", *name->ToCString()) == 0) { | |
1918 EmitIsArray(expr->arguments()); | |
1919 } else if (strcmp("_IsRegExp", *name->ToCString()) == 0) { | |
1920 EmitIsRegExp(expr->arguments()); | |
1921 } else if (strcmp("_IsConstructCall", *name->ToCString()) == 0) { | |
1922 EmitIsConstructCall(expr->arguments()); | |
1923 } else if (strcmp("_ObjectEquals", *name->ToCString()) == 0) { | |
1924 EmitObjectEquals(expr->arguments()); | |
1925 } else if (strcmp("_Arguments", *name->ToCString()) == 0) { | |
1926 EmitArguments(expr->arguments()); | |
1927 } else if (strcmp("_ArgumentsLength", *name->ToCString()) == 0) { | |
1928 EmitArgumentsLength(expr->arguments()); | |
1929 } else if (strcmp("_ClassOf", *name->ToCString()) == 0) { | |
1930 EmitClassOf(expr->arguments()); | |
1931 } else if (strcmp("_Log", *name->ToCString()) == 0) { | |
1932 EmitLog(expr->arguments()); | |
1933 } else if (strcmp("_RandomHeapNumber", *name->ToCString()) == 0) { | |
1934 EmitRandomHeapNumber(expr->arguments()); | |
1935 } else if (strcmp("_SubString", *name->ToCString()) == 0) { | |
1936 EmitSubString(expr->arguments()); | |
1937 } else if (strcmp("_RegExpExec", *name->ToCString()) == 0) { | |
1938 EmitRegExpExec(expr->arguments()); | |
1939 } else if (strcmp("_ValueOf", *name->ToCString()) == 0) { | |
1940 EmitValueOf(expr->arguments()); | |
1941 } else if (strcmp("_SetValueOf", *name->ToCString()) == 0) { | |
1942 EmitSetValueOf(expr->arguments()); | |
1943 } else if (strcmp("_NumberToString", *name->ToCString()) == 0) { | |
1944 EmitNumberToString(expr->arguments()); | |
1945 } else if (strcmp("_CharFromCode", *name->ToCString()) == 0) { | |
1946 EmitCharFromCode(expr->arguments()); | |
1947 } else if (strcmp("_FastCharCodeAt", *name->ToCString()) == 0) { | |
1948 EmitFastCharCodeAt(expr->arguments()); | |
1949 } else if (strcmp("_StringAdd", *name->ToCString()) == 0) { | |
1950 EmitStringAdd(expr->arguments()); | |
1951 } else if (strcmp("_StringCompare", *name->ToCString()) == 0) { | |
1952 EmitStringCompare(expr->arguments()); | |
1953 } else if (strcmp("_MathPow", *name->ToCString()) == 0) { | |
1954 EmitMathPow(expr->arguments()); | |
1955 } else if (strcmp("_MathSin", *name->ToCString()) == 0) { | |
1956 EmitMathSin(expr->arguments()); | |
1957 } else if (strcmp("_MathCos", *name->ToCString()) == 0) { | |
1958 EmitMathCos(expr->arguments()); | |
1959 } else if (strcmp("_MathSqrt", *name->ToCString()) == 0) { | |
1960 EmitMathSqrt(expr->arguments()); | |
1961 } else if (strcmp("_CallFunction", *name->ToCString()) == 0) { | |
1962 EmitCallFunction(expr->arguments()); | |
1963 } else if (strcmp("_RegExpConstructResult", *name->ToCString()) == 0) { | |
1964 EmitRegExpConstructResult(expr->arguments()); | |
1965 } else if (strcmp("_SwapElements", *name->ToCString()) == 0) { | |
1966 EmitSwapElements(expr->arguments()); | |
1967 } else if (strcmp("_GetFromCache", *name->ToCString()) == 0) { | |
1968 EmitGetFromCache(expr->arguments()); | |
1969 } else { | |
1970 UNREACHABLE(); | |
1971 } | |
1972 } | |
1973 | |
1974 | |
1975 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 1905 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
1976 ASSERT(args->length() == 1); | 1906 ASSERT(args->length() == 1); |
1977 | 1907 |
1978 VisitForValue(args->at(0), kAccumulator); | 1908 VisitForValue(args->at(0), kAccumulator); |
1979 | 1909 |
1980 Label materialize_true, materialize_false; | 1910 Label materialize_true, materialize_false; |
1981 Label* if_true = NULL; | 1911 Label* if_true = NULL; |
1982 Label* if_false = NULL; | 1912 Label* if_false = NULL; |
1983 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1913 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1984 | 1914 |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 | 2353 |
2424 // Load the argument on the stack and call the stub. | 2354 // Load the argument on the stack and call the stub. |
2425 VisitForValue(args->at(0), kStack); | 2355 VisitForValue(args->at(0), kStack); |
2426 | 2356 |
2427 NumberToStringStub stub; | 2357 NumberToStringStub stub; |
2428 __ CallStub(&stub); | 2358 __ CallStub(&stub); |
2429 Apply(context_, eax); | 2359 Apply(context_, eax); |
2430 } | 2360 } |
2431 | 2361 |
2432 | 2362 |
2433 void FullCodeGenerator::EmitCharFromCode(ZoneList<Expression*>* args) { | 2363 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
2434 ASSERT(args->length() == 1); | 2364 ASSERT(args->length() == 1); |
2435 | 2365 |
2436 VisitForValue(args->at(0), kAccumulator); | 2366 VisitForValue(args->at(0), kAccumulator); |
2437 | 2367 |
2438 Label slow_case, done; | 2368 Label done; |
2439 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 2369 StringCharFromCodeGenerator generator(eax, ebx); |
2440 ASSERT(kSmiTag == 0); | 2370 generator.GenerateFast(masm_); |
2441 ASSERT(kSmiShiftSize == 0); | |
2442 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); | |
2443 __ test(eax, | |
2444 Immediate(kSmiTagMask | | |
2445 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | |
2446 __ j(not_zero, &slow_case); | |
2447 __ Set(ebx, Immediate(Factory::single_character_string_cache())); | |
2448 ASSERT(kSmiTag == 0); | |
2449 ASSERT(kSmiTagSize == 1); | |
2450 ASSERT(kSmiShiftSize == 0); | |
2451 // At this point code register contains smi tagged ascii char code. | |
2452 __ mov(ebx, FieldOperand(ebx, | |
2453 eax, times_half_pointer_size, | |
2454 FixedArray::kHeaderSize)); | |
2455 __ cmp(ebx, Factory::undefined_value()); | |
2456 __ j(equal, &slow_case); | |
2457 __ mov(eax, ebx); | |
2458 __ jmp(&done); | 2371 __ jmp(&done); |
2459 | 2372 |
2460 __ bind(&slow_case); | 2373 NopRuntimeCallHelper call_helper; |
2461 __ push(eax); | 2374 generator.GenerateSlow(masm_, call_helper); |
2462 __ CallRuntime(Runtime::kCharFromCode, 1); | |
2463 | 2375 |
2464 __ bind(&done); | 2376 __ bind(&done); |
2465 Apply(context_, eax); | 2377 Apply(context_, ebx); |
2466 } | 2378 } |
2467 | 2379 |
2468 | 2380 |
2469 void FullCodeGenerator::EmitFastCharCodeAt(ZoneList<Expression*>* args) { | 2381 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { |
2470 // TODO(fsc): Port the complete implementation from the classic back-end. | 2382 ASSERT(args->length() == 2); |
| 2383 |
| 2384 VisitForValue(args->at(0), kStack); |
| 2385 VisitForValue(args->at(1), kAccumulator); |
| 2386 |
| 2387 Register object = ebx; |
| 2388 Register index = eax; |
| 2389 Register scratch = ecx; |
| 2390 Register result = edx; |
| 2391 |
| 2392 __ pop(object); |
| 2393 |
| 2394 Label need_conversion; |
| 2395 Label index_out_of_range; |
| 2396 Label done; |
| 2397 StringCharCodeAtGenerator generator(object, |
| 2398 index, |
| 2399 scratch, |
| 2400 result, |
| 2401 &need_conversion, |
| 2402 &need_conversion, |
| 2403 &index_out_of_range, |
| 2404 STRING_ANY_NUMBER_INDEX); |
| 2405 generator.GenerateFast(masm_); |
| 2406 __ jmp(&done); |
| 2407 |
| 2408 __ bind(&index_out_of_range); |
| 2409 // When the index is out of range, the spec requires us to return |
| 2410 // NaN. |
| 2411 __ Set(result, Immediate(Factory::nan_value())); |
| 2412 __ jmp(&done); |
| 2413 |
| 2414 __ bind(&need_conversion); |
2471 // Move the undefined value into the result register, which will | 2415 // Move the undefined value into the result register, which will |
2472 // trigger the slow case. | 2416 // trigger conversion. |
2473 __ Set(eax, Immediate(Factory::undefined_value())); | 2417 __ Set(result, Immediate(Factory::undefined_value())); |
2474 Apply(context_, eax); | 2418 __ jmp(&done); |
| 2419 |
| 2420 NopRuntimeCallHelper call_helper; |
| 2421 generator.GenerateSlow(masm_, call_helper); |
| 2422 |
| 2423 __ bind(&done); |
| 2424 Apply(context_, result); |
2475 } | 2425 } |
2476 | 2426 |
| 2427 |
| 2428 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { |
| 2429 ASSERT(args->length() == 2); |
| 2430 |
| 2431 VisitForValue(args->at(0), kStack); |
| 2432 VisitForValue(args->at(1), kAccumulator); |
| 2433 |
| 2434 Register object = ebx; |
| 2435 Register index = eax; |
| 2436 Register scratch1 = ecx; |
| 2437 Register scratch2 = edx; |
| 2438 Register result = eax; |
| 2439 |
| 2440 __ pop(object); |
| 2441 |
| 2442 Label need_conversion; |
| 2443 Label index_out_of_range; |
| 2444 Label done; |
| 2445 StringCharAtGenerator generator(object, |
| 2446 index, |
| 2447 scratch1, |
| 2448 scratch2, |
| 2449 result, |
| 2450 &need_conversion, |
| 2451 &need_conversion, |
| 2452 &index_out_of_range, |
| 2453 STRING_ANY_NUMBER_INDEX); |
| 2454 generator.GenerateFast(masm_); |
| 2455 __ jmp(&done); |
| 2456 |
| 2457 __ bind(&index_out_of_range); |
| 2458 // When the index is out of range, the spec requires us to return |
| 2459 // the empty string. |
| 2460 __ Set(result, Immediate(Factory::empty_string())); |
| 2461 __ jmp(&done); |
| 2462 |
| 2463 __ bind(&need_conversion); |
| 2464 // Move smi zero into the result register, which will trigger |
| 2465 // conversion. |
| 2466 __ Set(result, Immediate(Smi::FromInt(0))); |
| 2467 __ jmp(&done); |
| 2468 |
| 2469 NopRuntimeCallHelper call_helper; |
| 2470 generator.GenerateSlow(masm_, call_helper); |
| 2471 |
| 2472 __ bind(&done); |
| 2473 Apply(context_, result); |
| 2474 } |
| 2475 |
| 2476 |
2477 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { | 2477 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
2478 ASSERT_EQ(2, args->length()); | 2478 ASSERT_EQ(2, args->length()); |
2479 | 2479 |
2480 VisitForValue(args->at(0), kStack); | 2480 VisitForValue(args->at(0), kStack); |
2481 VisitForValue(args->at(1), kStack); | 2481 VisitForValue(args->at(1), kStack); |
2482 | 2482 |
2483 StringAddStub stub(NO_STRING_ADD_FLAGS); | 2483 StringAddStub stub(NO_STRING_ADD_FLAGS); |
2484 __ CallStub(&stub); | 2484 __ CallStub(&stub); |
2485 Apply(context_, eax); | 2485 Apply(context_, eax); |
2486 } | 2486 } |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3234 // And return. | 3234 // And return. |
3235 __ ret(0); | 3235 __ ret(0); |
3236 } | 3236 } |
3237 | 3237 |
3238 | 3238 |
3239 #undef __ | 3239 #undef __ |
3240 | 3240 |
3241 } } // namespace v8::internal | 3241 } } // namespace v8::internal |
3242 | 3242 |
3243 #endif // V8_TARGET_ARCH_IA32 | 3243 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |