Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |