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

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 436643002: Faster IC stubs by specializing them for Binary Smi operations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 10 matching lines...) Expand all
21 #include "vm/scopes.h" 21 #include "vm/scopes.h"
22 #include "vm/stub_code.h" 22 #include "vm/stub_code.h"
23 #include "vm/symbols.h" 23 #include "vm/symbols.h"
24 24
25 #include "vm/il_printer.h" 25 #include "vm/il_printer.h"
26 26
27 namespace dart { 27 namespace dart {
28 28
29 DEFINE_FLAG(bool, propagate_ic_data, true, 29 DEFINE_FLAG(bool, propagate_ic_data, true,
30 "Propagate IC data from unoptimized to optimized IC calls."); 30 "Propagate IC data from unoptimized to optimized IC calls.");
31 DEFINE_FLAG(bool, two_args_smi_icd, true,
32 "Generate special IC stubs for two args Smi operations");
31 DEFINE_FLAG(bool, unbox_numeric_fields, true, 33 DEFINE_FLAG(bool, unbox_numeric_fields, true,
32 "Support unboxed double and float32x4 fields."); 34 "Support unboxed double and float32x4 fields.");
33 DECLARE_FLAG(bool, enable_type_checks); 35 DECLARE_FLAG(bool, enable_type_checks);
34 DECLARE_FLAG(bool, eliminate_type_checks); 36 DECLARE_FLAG(bool, eliminate_type_checks);
35 DECLARE_FLAG(bool, trace_optimization); 37 DECLARE_FLAG(bool, trace_optimization);
36 DECLARE_FLAG(bool, trace_constant_propagation); 38 DECLARE_FLAG(bool, trace_constant_propagation);
37 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); 39 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
38 40
39 Definition::Definition() 41 Definition::Definition()
40 : range_(NULL), 42 : range_(NULL),
(...skipping 2351 matching lines...) Expand 10 before | Expand all | Expand 10 after
2392 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); 2394 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
2393 } 2395 }
2394 2396
2395 2397
2396 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate, 2398 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate,
2397 bool optimizing) const { 2399 bool optimizing) const {
2398 return MakeCallSummary(); 2400 return MakeCallSummary();
2399 } 2401 }
2400 2402
2401 2403
2404 static uword TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
2405 if (!FLAG_two_args_smi_icd) {
2406 return 0;
2407 }
2408 StubCode* stub_code = Isolate::Current()->stub_code();
2409 switch (kind) {
2410 case Token::kADD: return stub_code->SmiAddInlineCacheEntryPoint();
2411 case Token::kSUB: return stub_code->SmiSubInlineCacheEntryPoint();
2412 case Token::kEQ: return stub_code->SmiEqualInlineCacheEntryPoint();
2413 default: return 0;
2414 }
2415 }
2416
2417
2402 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2418 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2419 Isolate* isolate = compiler->isolate();
2403 const ICData* call_ic_data = NULL; 2420 const ICData* call_ic_data = NULL;
2404 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { 2421 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) {
2405 const Array& arguments_descriptor = 2422 const Array& arguments_descriptor =
2406 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 2423 Array::Handle(isolate, ArgumentsDescriptor::New(ArgumentCount(),
2407 argument_names())); 2424 argument_names()));
2408 call_ic_data = compiler->GetOrAddInstanceCallICData( 2425 call_ic_data = compiler->GetOrAddInstanceCallICData(
2409 deopt_id(), function_name(), arguments_descriptor, 2426 deopt_id(), function_name(), arguments_descriptor,
2410 checked_argument_count()); 2427 checked_argument_count());
2411 } else { 2428 } else {
2412 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); 2429 call_ic_data = &ICData::ZoneHandle(isolate, ic_data()->raw());
2413 } 2430 }
2414 if (compiler->is_optimizing()) { 2431 if (compiler->is_optimizing()) {
2415 ASSERT(HasICData()); 2432 ASSERT(HasICData());
2416 if (ic_data()->NumberOfChecks() > 0) { 2433 if (ic_data()->NumberOfUsedChecks() > 0) {
2417 const ICData& unary_ic_data = 2434 const ICData& unary_ic_data =
2418 ICData::ZoneHandle(ic_data()->AsUnaryClassChecks()); 2435 ICData::ZoneHandle(isolate, ic_data()->AsUnaryClassChecks());
2419 compiler->GenerateInstanceCall(deopt_id(), 2436 compiler->GenerateInstanceCall(deopt_id(),
2420 token_pos(), 2437 token_pos(),
2421 ArgumentCount(), 2438 ArgumentCount(),
2422 locs(), 2439 locs(),
2423 unary_ic_data); 2440 unary_ic_data);
2424 } else { 2441 } else {
2425 // Call was not visited yet, use original ICData in order to populate it. 2442 // Call was not visited yet, use original ICData in order to populate it.
2426 compiler->GenerateInstanceCall(deopt_id(), 2443 compiler->GenerateInstanceCall(deopt_id(),
2427 token_pos(), 2444 token_pos(),
2428 ArgumentCount(), 2445 ArgumentCount(),
2429 locs(), 2446 locs(),
2430 *call_ic_data); 2447 *call_ic_data);
2431 } 2448 }
2432 } else { 2449 } else {
2433 // Unoptimized code. 2450 // Unoptimized code.
2434 ASSERT(!HasICData()); 2451 ASSERT(!HasICData());
2435 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 2452 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
2436 deopt_id(), 2453 deopt_id(),
2437 token_pos()); 2454 token_pos());
2438 compiler->GenerateInstanceCall(deopt_id(), 2455 bool is_smi_two_args_op = false;
2439 token_pos(), 2456 const uword label_address = TwoArgsSmiOpInlineCacheEntry(token_kind());
2440 ArgumentCount(), 2457 if (label_address != 0) {
2441 locs(), 2458 // We have a dedicated inline cache stub for this operation, add an
2442 *call_ic_data); 2459 // an initial Smi/Smi check with count 0.
2460 ASSERT(call_ic_data->NumArgsTested() == 2);
2461 const String& name = String::Handle(isolate, call_ic_data->target_name());
2462 const Class& smi_class = Class::Handle(isolate, Smi::Class());
2463 const Function& smi_op_target =
2464 Function::Handle(Resolver::ResolveDynamicAnyArgs(smi_class, name));
2465 if (call_ic_data->NumberOfChecks() == 0) {
2466 GrowableArray<intptr_t> class_ids(2);
2467 class_ids.Add(kSmiCid);
2468 class_ids.Add(kSmiCid);
2469 call_ic_data->AddCheck(class_ids, smi_op_target);
2470 // 'AddCheck' sets the initial count to 1.
2471 call_ic_data->SetCountAt(0, 0);
2472 is_smi_two_args_op = true;
2473 } else if (call_ic_data->NumberOfChecks() == 1) {
2474 GrowableArray<intptr_t> class_ids(2);
2475 Function& target = Function::Handle(isolate);
2476 call_ic_data->GetCheckAt(0, &class_ids, &target);
2477 if ((target.raw() == smi_op_target.raw()) &&
2478 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
2479 is_smi_two_args_op = true;
2480 }
2481 }
zra 2014/08/20 20:17:10 Not sure if it makes sense to have an assertion he
srdjan 2014/08/21 17:30:22 I modify IC Data only if there are no previous che
2482 }
2483 if (is_smi_two_args_op) {
2484 ASSERT(ArgumentCount() == 2);
2485 ExternalLabel target_label(label_address);
2486 compiler->EmitInstanceCall(&target_label, *call_ic_data, ArgumentCount(),
2487 deopt_id(), token_pos(), locs());
2488 } else {
2489 compiler->GenerateInstanceCall(deopt_id(),
2490 token_pos(),
2491 ArgumentCount(),
2492 locs(),
2493 *call_ic_data);
2494 }
2443 } 2495 }
2444 } 2496 }
2445 2497
2446 2498
2447 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { 2499 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const {
2448 return ic_data().HasOneTarget() && 2500 return ic_data().HasOneTarget() &&
2449 (MethodRecognizer::RecognizeKind( 2501 (MethodRecognizer::RecognizeKind(
2450 Function::Handle(ic_data().GetTargetAt(0))) != 2502 Function::Handle(ic_data().GetTargetAt(0))) !=
2451 MethodRecognizer::kUnknown); 2503 MethodRecognizer::kUnknown);
2452 } 2504 }
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 case Token::kTRUNCDIV: return 0; 3022 case Token::kTRUNCDIV: return 0;
2971 case Token::kMOD: return 1; 3023 case Token::kMOD: return 1;
2972 default: UNIMPLEMENTED(); return -1; 3024 default: UNIMPLEMENTED(); return -1;
2973 } 3025 }
2974 } 3026 }
2975 3027
2976 3028
2977 #undef __ 3029 #undef __
2978 3030
2979 } // namespace dart 3031 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698