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