Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: src/ic.cc

Issue 25494007: Reland "Hydrogenisation of binops" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/isolate.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 2311 matching lines...) Expand 10 before | Expand all | Expand 10 after
2322 StrictModeFlag strict_mode = ic.strict_mode(); 2322 StrictModeFlag strict_mode = ic.strict_mode();
2323 return Runtime::SetObjectProperty(isolate, 2323 return Runtime::SetObjectProperty(isolate,
2324 object, 2324 object,
2325 key, 2325 key,
2326 value, 2326 value,
2327 NONE, 2327 NONE,
2328 strict_mode); 2328 strict_mode);
2329 } 2329 }
2330 2330
2331 2331
2332 void BinaryOpIC::patch(Code* code) {
2333 set_target(code);
2334 }
2335
2336
2337 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2332 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2338 switch (type_info) { 2333 switch (type_info) {
2339 case UNINITIALIZED: return "Uninitialized"; 2334 case UNINITIALIZED: return "Uninitialized";
2340 case SMI: return "Smi"; 2335 case SMI: return "Smi";
2341 case INT32: return "Int32"; 2336 case INT32: return "Int32";
2342 case NUMBER: return "Number"; 2337 case NUMBER: return "Number";
2343 case ODDBALL: return "Oddball"; 2338 case ODDBALL: return "Oddball";
2344 case STRING: return "String"; 2339 case STRING: return "String";
2345 case GENERIC: return "Generic"; 2340 case GENERIC: return "Generic";
2346 default: return "Invalid"; 2341 default: return "Invalid";
2347 } 2342 }
2348 } 2343 }
2349 2344
2350 2345
2351 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { 2346 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2352 switch (type_info) { 2347 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2353 case UNINITIALIZED: 2348 BinaryOpStub stub(extra_ic_state);
2354 return ::v8::internal::UNINITIALIZED; 2349
2355 case SMI: 2350 bool smi_was_enabled = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2356 case INT32: 2351 stub.GetRightType(isolate())->Maybe(Type::Smi());
2357 case NUMBER: 2352
2358 case ODDBALL: 2353 Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2359 case STRING: 2354
2360 return MONOMORPHIC; 2355 #ifdef DEBUG
2361 case GENERIC: 2356 if (FLAG_trace_ic) {
2362 return ::v8::internal::GENERIC; 2357 char buffer[100];
2358 NoAllocationStringAllocator allocator(buffer,
2359 static_cast<unsigned>(sizeof(buffer)));
2360 StringStream stream(&allocator);
2361 stream.Add("[");
2362 stub.PrintName(&stream);
2363
2364 stub.UpdateStatus(left, right, result);
2365
2366 stream.Add(" => ");
2367 stub.PrintState(&stream);
2368 stream.Add(" ");
2369 stream.OutputToStdOut();
2370 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2371 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2372 PrintF("]\n");
2373 } else {
2374 stub.UpdateStatus(left, right, result);
2363 } 2375 }
2364 UNREACHABLE(); 2376 #else
2365 return ::v8::internal::UNINITIALIZED; 2377 stub.UpdateStatus(left, right, result);
2378 #endif
2379
2380 Handle<Code> code = stub.GetCode(isolate());
2381 set_target(*code);
2382
2383 bool enable_smi = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2384 stub.GetRightType(isolate())->Maybe(Type::Smi());
2385
2386 if (!smi_was_enabled && enable_smi) {
2387 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2388 } else if (smi_was_enabled && !enable_smi) {
2389 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2390 }
2391
2392 return result.has_value
2393 ? static_cast<MaybeObject*>(*result.value)
2394 : Failure::Exception();
2366 } 2395 }
2367 2396
2368 2397
2369 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type, 2398 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2370 Isolate* isolate) { 2399 HandleScope scope(isolate);
2371 switch (binary_type) { 2400 Handle<Object> left = args.at<Object>(0);
2372 case UNINITIALIZED: 2401 Handle<Object> right = args.at<Object>(1);
2373 return handle(Type::None(), isolate); 2402 BinaryOpIC ic(isolate);
2374 case SMI: 2403 return ic.Transition(left, right);
2375 return handle(Type::Smi(), isolate);
2376 case INT32:
2377 return handle(Type::Signed32(), isolate);
2378 case NUMBER:
2379 return handle(Type::Number(), isolate);
2380 case ODDBALL:
2381 return handle(Type::Optional(
2382 handle(Type::Union(
2383 handle(Type::Number(), isolate),
2384 handle(Type::String(), isolate)), isolate)), isolate);
2385 case STRING:
2386 return handle(Type::String(), isolate);
2387 case GENERIC:
2388 return handle(Type::Any(), isolate);
2389 }
2390 UNREACHABLE();
2391 return handle(Type::Any(), isolate);
2392 } 2404 }
2393 2405
2394 2406
2395 void BinaryOpIC::StubInfoToType(int minor_key,
2396 Handle<Type>* left,
2397 Handle<Type>* right,
2398 Handle<Type>* result,
2399 Isolate* isolate) {
2400 TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
2401 BinaryOpStub::decode_types_from_minor_key(
2402 minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
2403 *left = TypeInfoToType(left_typeinfo, isolate);
2404 *right = TypeInfoToType(right_typeinfo, isolate);
2405 *result = TypeInfoToType(result_typeinfo, isolate);
2406 }
2407
2408
2409 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
2410 Token::Value op) {
2411 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
2412 if (type.IsSmi()) return BinaryOpIC::SMI;
2413 if (type.IsInteger32()) {
2414 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2415 return BinaryOpIC::INT32;
2416 }
2417 if (type.IsNumber()) return BinaryOpIC::NUMBER;
2418 if (type.IsString()) return BinaryOpIC::STRING;
2419 if (value->IsUndefined()) {
2420 if (op == Token::BIT_AND ||
2421 op == Token::BIT_OR ||
2422 op == Token::BIT_XOR ||
2423 op == Token::SAR ||
2424 op == Token::SHL ||
2425 op == Token::SHR) {
2426 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2427 return BinaryOpIC::INT32;
2428 }
2429 return BinaryOpIC::ODDBALL;
2430 }
2431 return BinaryOpIC::GENERIC;
2432 }
2433
2434
2435 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type,
2436 Handle<Object> value,
2437 Token::Value op) {
2438 BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op);
2439 if (old_type == BinaryOpIC::STRING) {
2440 if (new_type == BinaryOpIC::STRING) return new_type;
2441 return BinaryOpIC::GENERIC;
2442 }
2443 return Max(old_type, new_type);
2444 }
2445
2446
2447 #ifdef DEBUG
2448 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
2449 BinaryOpIC::TypeInfo right,
2450 Maybe<int32_t> fixed_right_arg,
2451 BinaryOpIC::TypeInfo result) {
2452 PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
2453 if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
2454 PrintF("->%s", BinaryOpIC::GetName(result));
2455 }
2456 #endif
2457
2458
2459 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2460 ASSERT(args.length() == 3);
2461
2462 HandleScope scope(isolate);
2463 Handle<Object> left = args.at<Object>(0);
2464 Handle<Object> right = args.at<Object>(1);
2465 int key = args.smi_at(2);
2466 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
2467
2468 BinaryOpIC::TypeInfo previous_left, previous_right, previous_result;
2469 BinaryOpStub::decode_types_from_minor_key(
2470 key, &previous_left, &previous_right, &previous_result);
2471
2472 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
2473 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
2474 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2475
2476 // STRING is only used for ADD operations.
2477 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
2478 op != Token::ADD) {
2479 new_left = new_right = BinaryOpIC::GENERIC;
2480 }
2481
2482 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
2483 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
2484
2485 Maybe<int> previous_fixed_right_arg =
2486 BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);
2487
2488 int32_t value;
2489 bool new_has_fixed_right_arg =
2490 op == Token::MOD &&
2491 right->ToInt32(&value) &&
2492 BinaryOpStub::can_encode_arg_value(value) &&
2493 (previous_overall == BinaryOpIC::UNINITIALIZED ||
2494 (previous_fixed_right_arg.has_value &&
2495 previous_fixed_right_arg.value == value));
2496 Maybe<int32_t> new_fixed_right_arg(
2497 new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);
2498
2499 if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) {
2500 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
2501 if (op == Token::DIV ||
2502 op == Token::MUL ||
2503 op == Token::SHR ||
2504 SmiValuesAre32Bits()) {
2505 // Arithmetic on two Smi inputs has yielded a heap number.
2506 // That is the only way to get here from the Smi stub.
2507 // With 32-bit Smis, all overflows give heap numbers, but with
2508 // 31-bit Smis, most operations overflow to int32 results.
2509 result_type = BinaryOpIC::NUMBER;
2510 } else {
2511 // Other operations on SMIs that overflow yield int32s.
2512 result_type = BinaryOpIC::INT32;
2513 }
2514 }
2515 if (new_overall == BinaryOpIC::INT32 &&
2516 previous_overall == BinaryOpIC::INT32) {
2517 if (new_left == previous_left && new_right == previous_right) {
2518 result_type = BinaryOpIC::NUMBER;
2519 }
2520 }
2521 }
2522
2523 BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
2524 Handle<Code> code = stub.GetCode(isolate);
2525 if (!code.is_null()) {
2526 #ifdef DEBUG
2527 if (FLAG_trace_ic) {
2528 PrintF("[BinaryOpIC in ");
2529 JavaScriptFrame::PrintTop(isolate, stdout, false, true);
2530 PrintF(" ");
2531 TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
2532 previous_result);
2533 PrintF(" => ");
2534 TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
2535 PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
2536 }
2537 #endif
2538 BinaryOpIC ic(isolate);
2539 ic.patch(*code);
2540
2541 // Activate inlined smi code.
2542 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2543 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2544 }
2545 }
2546
2547 Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
2548 Object* builtin = NULL; // Initialization calms down the compiler.
2549 switch (op) {
2550 case Token::ADD:
2551 builtin = builtins->javascript_builtin(Builtins::ADD);
2552 break;
2553 case Token::SUB:
2554 builtin = builtins->javascript_builtin(Builtins::SUB);
2555 break;
2556 case Token::MUL:
2557 builtin = builtins->javascript_builtin(Builtins::MUL);
2558 break;
2559 case Token::DIV:
2560 builtin = builtins->javascript_builtin(Builtins::DIV);
2561 break;
2562 case Token::MOD:
2563 builtin = builtins->javascript_builtin(Builtins::MOD);
2564 break;
2565 case Token::BIT_AND:
2566 builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2567 break;
2568 case Token::BIT_OR:
2569 builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2570 break;
2571 case Token::BIT_XOR:
2572 builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2573 break;
2574 case Token::SHR:
2575 builtin = builtins->javascript_builtin(Builtins::SHR);
2576 break;
2577 case Token::SAR:
2578 builtin = builtins->javascript_builtin(Builtins::SAR);
2579 break;
2580 case Token::SHL:
2581 builtin = builtins->javascript_builtin(Builtins::SHL);
2582 break;
2583 default:
2584 UNREACHABLE();
2585 }
2586
2587 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2588
2589 bool caught_exception;
2590 Handle<Object> builtin_args[] = { right };
2591 Handle<Object> result = Execution::Call(isolate,
2592 builtin_function,
2593 left,
2594 ARRAY_SIZE(builtin_args),
2595 builtin_args,
2596 &caught_exception);
2597 if (caught_exception) {
2598 return Failure::Exception();
2599 }
2600 return *result;
2601 }
2602
2603
2604 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2407 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2605 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2408 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2606 Code* code = NULL; 2409 Code* code = NULL;
2607 CHECK(stub.FindCodeInCache(&code, isolate)); 2410 CHECK(stub.FindCodeInCache(&code, isolate));
2608 return code; 2411 return code;
2609 } 2412 }
2610 2413
2611 2414
2612 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2415 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2613 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2416 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
2891 } 2694 }
2892 2695
2893 2696
2894 RUNTIME_FUNCTION(MaybeObject*, Unreachable) { 2697 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
2895 UNREACHABLE(); 2698 UNREACHABLE();
2896 CHECK(false); 2699 CHECK(false);
2897 return isolate->heap()->undefined_value(); 2700 return isolate->heap()->undefined_value();
2898 } 2701 }
2899 2702
2900 2703
2704 Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
2705 switch (op) {
2706 default:
2707 UNREACHABLE();
2708 case Token::ADD:
2709 return Builtins::ADD;
2710 break;
2711 case Token::SUB:
2712 return Builtins::SUB;
2713 break;
2714 case Token::MUL:
2715 return Builtins::MUL;
2716 break;
2717 case Token::DIV:
2718 return Builtins::DIV;
2719 break;
2720 case Token::MOD:
2721 return Builtins::MOD;
2722 break;
2723 case Token::BIT_OR:
2724 return Builtins::BIT_OR;
2725 break;
2726 case Token::BIT_AND:
2727 return Builtins::BIT_AND;
2728 break;
2729 case Token::BIT_XOR:
2730 return Builtins::BIT_XOR;
2731 break;
2732 case Token::SAR:
2733 return Builtins::SAR;
2734 break;
2735 case Token::SHR:
2736 return Builtins::SHR;
2737 break;
2738 case Token::SHL:
2739 return Builtins::SHL;
2740 break;
2741 }
2742 }
2743
2744
2901 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, 2745 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
2902 Code::ExtraICState extra_ic_state) { 2746 Code::ExtraICState extra_ic_state) {
2903 ToBooleanStub stub(extra_ic_state); 2747 ToBooleanStub stub(extra_ic_state);
2904 bool to_boolean_value = stub.UpdateStatus(object); 2748 bool to_boolean_value = stub.UpdateStatus(object);
2905 Handle<Code> code = stub.GetCode(isolate()); 2749 Handle<Code> code = stub.GetCode(isolate());
2906 set_target(*code); 2750 set_target(*code);
2907 return Smi::FromInt(to_boolean_value ? 1 : 0); 2751 return Smi::FromInt(to_boolean_value ? 1 : 0);
2908 } 2752 }
2909 2753
2910 2754
(...skipping 14 matching lines...) Expand all
2925 #undef ADDR 2769 #undef ADDR
2926 }; 2770 };
2927 2771
2928 2772
2929 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2773 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2930 return IC_utilities[id]; 2774 return IC_utilities[id];
2931 } 2775 }
2932 2776
2933 2777
2934 } } // namespace v8::internal 2778 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/isolate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698