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

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 11 matching lines...) Expand all
22 #include "vm/scopes.h" 22 #include "vm/scopes.h"
23 #include "vm/stub_code.h" 23 #include "vm/stub_code.h"
24 #include "vm/symbols.h" 24 #include "vm/symbols.h"
25 25
26 #include "vm/il_printer.h" 26 #include "vm/il_printer.h"
27 27
28 namespace dart { 28 namespace dart {
29 29
30 DEFINE_FLAG(bool, propagate_ic_data, true, 30 DEFINE_FLAG(bool, propagate_ic_data, true,
31 "Propagate IC data from unoptimized to optimized IC calls."); 31 "Propagate IC data from unoptimized to optimized IC calls.");
32 DEFINE_FLAG(bool, two_args_smi_icd, true,
33 "Generate special IC stubs for two args Smi operations");
32 DEFINE_FLAG(bool, unbox_numeric_fields, true, 34 DEFINE_FLAG(bool, unbox_numeric_fields, true,
33 "Support unboxed double and float32x4 fields."); 35 "Support unboxed double and float32x4 fields.");
34 DECLARE_FLAG(bool, enable_type_checks); 36 DECLARE_FLAG(bool, enable_type_checks);
35 DECLARE_FLAG(bool, eliminate_type_checks); 37 DECLARE_FLAG(bool, eliminate_type_checks);
36 DECLARE_FLAG(bool, trace_optimization); 38 DECLARE_FLAG(bool, trace_optimization);
37 DECLARE_FLAG(bool, trace_constant_propagation); 39 DECLARE_FLAG(bool, trace_constant_propagation);
38 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); 40 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
39 41
40 Definition::Definition() 42 Definition::Definition()
41 : range_(NULL), 43 : range_(NULL),
(...skipping 2183 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); 2227 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
2226 } 2228 }
2227 2229
2228 2230
2229 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate, 2231 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate,
2230 bool optimizing) const { 2232 bool optimizing) const {
2231 return MakeCallSummary(); 2233 return MakeCallSummary();
2232 } 2234 }
2233 2235
2234 2236
2237 static uword TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
2238 if (!FLAG_two_args_smi_icd) {
2239 return 0;
2240 }
2241 StubCode* stub_code = Isolate::Current()->stub_code();
2242 switch (kind) {
2243 case Token::kADD: return stub_code->SmiAddInlineCacheEntryPoint();
2244 case Token::kSUB: return stub_code->SmiSubInlineCacheEntryPoint();
2245 case Token::kEQ: return stub_code->SmiEqualInlineCacheEntryPoint();
2246 default: return 0;
2247 }
2248 }
2249
2250
2235 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2251 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2252 Isolate* isolate = compiler->isolate();
2236 const ICData* call_ic_data = NULL; 2253 const ICData* call_ic_data = NULL;
2237 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { 2254 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) {
2238 const Array& arguments_descriptor = 2255 const Array& arguments_descriptor =
2239 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 2256 Array::Handle(isolate, ArgumentsDescriptor::New(ArgumentCount(),
2240 argument_names())); 2257 argument_names()));
2241 call_ic_data = compiler->GetOrAddInstanceCallICData( 2258 call_ic_data = compiler->GetOrAddInstanceCallICData(
2242 deopt_id(), function_name(), arguments_descriptor, 2259 deopt_id(), function_name(), arguments_descriptor,
2243 checked_argument_count()); 2260 checked_argument_count());
2244 } else { 2261 } else {
2245 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); 2262 call_ic_data = &ICData::ZoneHandle(isolate, ic_data()->raw());
2246 } 2263 }
2247 if (compiler->is_optimizing()) { 2264 if (compiler->is_optimizing()) {
2248 ASSERT(HasICData()); 2265 ASSERT(HasICData());
2249 if (ic_data()->NumberOfChecks() > 0) { 2266 if (ic_data()->NumberOfUsedChecks() > 0) {
2250 const ICData& unary_ic_data = 2267 const ICData& unary_ic_data =
2251 ICData::ZoneHandle(ic_data()->AsUnaryClassChecks()); 2268 ICData::ZoneHandle(isolate, ic_data()->AsUnaryClassChecks());
2252 compiler->GenerateInstanceCall(deopt_id(), 2269 compiler->GenerateInstanceCall(deopt_id(),
2253 token_pos(), 2270 token_pos(),
2254 ArgumentCount(), 2271 ArgumentCount(),
2255 locs(), 2272 locs(),
2256 unary_ic_data); 2273 unary_ic_data);
2257 } else { 2274 } else {
2258 // Call was not visited yet, use original ICData in order to populate it. 2275 // Call was not visited yet, use original ICData in order to populate it.
2259 compiler->GenerateInstanceCall(deopt_id(), 2276 compiler->GenerateInstanceCall(deopt_id(),
2260 token_pos(), 2277 token_pos(),
2261 ArgumentCount(), 2278 ArgumentCount(),
2262 locs(), 2279 locs(),
2263 *call_ic_data); 2280 *call_ic_data);
2264 } 2281 }
2265 } else { 2282 } else {
2266 // Unoptimized code. 2283 // Unoptimized code.
2267 ASSERT(!HasICData()); 2284 ASSERT(!HasICData());
2268 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 2285 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
2269 deopt_id(), 2286 deopt_id(),
2270 token_pos()); 2287 token_pos());
2271 compiler->GenerateInstanceCall(deopt_id(), 2288 bool is_smi_two_args_op = false;
2272 token_pos(), 2289 const uword label_address = TwoArgsSmiOpInlineCacheEntry(token_kind());
2273 ArgumentCount(), 2290 if (label_address != 0) {
2274 locs(), 2291 // We have a dedicated inline cache stub for this operation, add an
2275 *call_ic_data); 2292 // an initial Smi/Smi check with count 0.
2293 ASSERT(call_ic_data->NumArgsTested() == 2);
2294 const String& name = String::Handle(isolate, call_ic_data->target_name());
2295 const Class& smi_class = Class::Handle(isolate, Smi::Class());
2296 const Function& smi_op_target =
2297 Function::Handle(Resolver::ResolveDynamicAnyArgs(smi_class, name));
2298 if (call_ic_data->NumberOfChecks() == 0) {
2299 GrowableArray<intptr_t> class_ids(2);
2300 class_ids.Add(kSmiCid);
2301 class_ids.Add(kSmiCid);
2302 call_ic_data->AddCheck(class_ids, smi_op_target);
2303 // 'AddCheck' sets the initial count to 1.
2304 call_ic_data->SetCountAt(0, 0);
2305 is_smi_two_args_op = true;
2306 } else if (call_ic_data->NumberOfChecks() == 1) {
2307 GrowableArray<intptr_t> class_ids(2);
2308 Function& target = Function::Handle(isolate);
2309 call_ic_data->GetCheckAt(0, &class_ids, &target);
2310 if ((target.raw() == smi_op_target.raw()) &&
2311 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
2312 is_smi_two_args_op = true;
2313 }
2314 }
2315 }
2316 if (is_smi_two_args_op) {
2317 ASSERT(ArgumentCount() == 2);
2318 ExternalLabel target_label(label_address);
2319 compiler->EmitInstanceCall(&target_label, *call_ic_data, ArgumentCount(),
2320 deopt_id(), token_pos(), locs());
2321 } else {
2322 compiler->GenerateInstanceCall(deopt_id(),
2323 token_pos(),
2324 ArgumentCount(),
2325 locs(),
2326 *call_ic_data);
2327 }
2276 } 2328 }
2277 } 2329 }
2278 2330
2279 2331
2280 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { 2332 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const {
2281 return ic_data().HasOneTarget() && 2333 return ic_data().HasOneTarget() &&
2282 (MethodRecognizer::RecognizeKind( 2334 (MethodRecognizer::RecognizeKind(
2283 Function::Handle(ic_data().GetTargetAt(0))) != 2335 Function::Handle(ic_data().GetTargetAt(0))) !=
2284 MethodRecognizer::kUnknown); 2336 MethodRecognizer::kUnknown);
2285 } 2337 }
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
2809 case Token::kTRUNCDIV: return 0; 2861 case Token::kTRUNCDIV: return 0;
2810 case Token::kMOD: return 1; 2862 case Token::kMOD: return 1;
2811 default: UNIMPLEMENTED(); return -1; 2863 default: UNIMPLEMENTED(); return -1;
2812 } 2864 }
2813 } 2865 }
2814 2866
2815 2867
2816 #undef __ 2868 #undef __
2817 2869
2818 } // namespace dart 2870 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698