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

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

Issue 513213002: Generate some intrinsics using our IR. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // Class for intrinsifying functions. 4 // Class for intrinsifying functions.
5 5
6 #include "vm/assembler.h" 6 #include "vm/assembler.h"
7 #include "vm/intrinsifier.h" 7 #include "vm/intrinsifier.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/symbols.h" 10 #include "vm/symbols.h"
11 11
12 #include "vm/flow_graph.h"
13 #include "vm/flow_graph_compiler.h"
14 #include "vm/flow_graph_allocator.h"
15 #include "vm/flow_graph_builder.h"
16 #include "vm/il_printer.h"
17 #include "vm/intermediate_language.h"
18 #include "vm/parser.h"
19
12 namespace dart { 20 namespace dart {
13 21
14 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); 22 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
15 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); 23 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
24 DECLARE_FLAG(bool, code_comments);
25 DECLARE_FLAG(bool, print_flow_graph);
26 DECLARE_FLAG(bool, print_flow_graph_optimized);
16 27
17 bool Intrinsifier::CanIntrinsify(const Function& function) { 28 bool Intrinsifier::CanIntrinsify(const Function& function) {
18 if (!FLAG_intrinsify) return false; 29 if (!FLAG_intrinsify) return false;
19 if (function.IsClosureFunction()) return false; 30 if (function.IsClosureFunction()) return false;
20 // Can occur because of compile-all flag. 31 // Can occur because of compile-all flag.
21 if (function.is_external()) return false; 32 if (function.is_external()) return false;
22 return function.is_intrinsic(); 33 return function.is_intrinsic();
23 } 34 }
24 35
25 36
(...skipping 26 matching lines...) Expand all
52 func = cls.LookupFunctionAllowPrivate(str); \ 63 func = cls.LookupFunctionAllowPrivate(str); \
53 } \ 64 } \
54 ASSERT(!func.IsNull()); \ 65 ASSERT(!func.IsNull()); \
55 func.set_is_intrinsic(true); 66 func.set_is_intrinsic(true);
56 67
57 // Set up all core lib functions that can be intrisified. 68 // Set up all core lib functions that can be intrisified.
58 lib = Library::CoreLibrary(); 69 lib = Library::CoreLibrary();
59 ASSERT(!lib.IsNull()); 70 ASSERT(!lib.IsNull());
60 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 71 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
61 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 72 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
73 GRAPH_CORE_INTRINSICS_LIST(SETUP_FUNCTION);
62 74
63 // Set up all math lib functions that can be intrisified. 75 // Set up all math lib functions that can be intrisified.
64 lib = Library::MathLibrary(); 76 lib = Library::MathLibrary();
65 ASSERT(!lib.IsNull()); 77 ASSERT(!lib.IsNull());
66 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 78 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
67 79
68 // Set up all dart:typed_data lib functions that can be intrisified. 80 // Set up all dart:typed_data lib functions that can be intrisified.
69 lib = Library::TypedDataLibrary(); 81 lib = Library::TypedDataLibrary();
70 ASSERT(!lib.IsNull()); 82 ASSERT(!lib.IsNull());
71 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 83 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
84 GRAPH_TYPED_DATA_INTRINSICS_LIST(SETUP_FUNCTION);
72 85
73 // Setup all dart:profiler lib functions that can be intrinsified. 86 // Setup all dart:profiler lib functions that can be intrinsified.
74 lib = Library::ProfilerLibrary(); 87 lib = Library::ProfilerLibrary();
75 ASSERT(!lib.IsNull()); 88 ASSERT(!lib.IsNull());
76 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 89 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
77 90
78 #undef SETUP_FUNCTION 91 #undef SETUP_FUNCTION
79 } 92 }
80 93
81 94
82 void Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { 95 static void EmitCodeFor(FlowGraphCompiler* compiler,
96 FlowGraph* graph) {
97 compiler->assembler()->Comment("Graph intrinsic");
98 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) {
99 BlockEntryInstr* block = graph->reverse_postorder()[i];
100 if (block->IsGraphEntry()) continue; // No code for graph entry needed.
101 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
102 Instruction* instr = it.Current();
103 if (FLAG_code_comments) compiler->EmitComment(instr);
104 if (instr->IsParallelMove()) {
105 compiler->parallel_move_resolver()->EmitNativeCode(
106 instr->AsParallelMove());
107 } else {
108 ASSERT(instr->locs() != NULL);
109 // Calls are not supported in intrinsics code.
110 ASSERT(!instr->locs()->always_calls());
111 // Intrinsic code only allows constants that can always be loaded
112 // without constant pool on all platforms. There is no constant pool
113 // register set up in intrinsic code. We could allow old-space constants
114 // as they don't move, but restrict to smi and VM objects for now.
115 ASSERT(!instr->IsConstant() ||
116 (instr->AsConstant()->value().IsSmi() ||
117 instr->AsConstant()->value().InVMHeap()));
118 instr->EmitNativeCode(compiler);
119 }
120 }
121 }
122 }
123
124
125 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
126 FlowGraphCompiler* compiler) {
127 ZoneGrowableArray<const ICData*>* ic_data_array =
128 new ZoneGrowableArray<const ICData*>();
129 FlowGraphBuilder builder(const_cast<ParsedFunction*>(&parsed_function),
130 *ic_data_array,
131 NULL, // NULL = not inlining.
132 -1); // No OSR id.
133
134 intptr_t block_id = builder.AllocateBlockId();
135 TargetEntryInstr* normal_entry =
136 new TargetEntryInstr(block_id,
137 CatchClauseNode::kInvalidTryIndex);
138 GraphEntryInstr* graph_entry = new GraphEntryInstr(
139 &parsed_function, normal_entry, -1); // No OSR id.
140 FlowGraph* graph = new FlowGraph(builder, graph_entry, block_id);
141 const Function& function = parsed_function.function();
142 switch (function.recognized_kind()) {
143 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \
144 case MethodRecognizer::k##enum_name: \
145 ASSERT(function.CheckSourceFingerprint(fp)); \
146 if (!Build_##enum_name(graph)) return false; \
147 break;
148
149 GRAPH_INTRINSICS_LIST(EMIT_CASE);
150 default:
151 return false;
152 #undef EMIT_CASE
153 }
154
155 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
156 OS::Print("Intrinsic graph before\n");
157 FlowGraphPrinter printer(*graph);
158 printer.PrintBlocks();
159 }
160
161 // Perform register allocation on the SSA graph.
162 FlowGraphAllocator allocator(*graph, true); // Intrinsic mode.
163 allocator.AllocateRegisters();
164
165 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
166 OS::Print("Intrinsic graph after\n");
167 FlowGraphPrinter printer(*graph);
168 printer.PrintBlocks();
169 }
170 EmitCodeFor(compiler, graph);
171 return true;
172 }
173
174
175 void Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
176 FlowGraphCompiler* compiler) {
177 const Function& function = parsed_function.function();
83 if (!CanIntrinsify(function)) return; 178 if (!CanIntrinsify(function)) return;
84 179
180 if (GraphIntrinsify(parsed_function, compiler)) return;
181
182
85 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \ 183 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \
86 case MethodRecognizer::k##enum_name: \ 184 case MethodRecognizer::k##enum_name: \
87 ASSERT(function.CheckSourceFingerprint(fp)); \ 185 ASSERT(function.CheckSourceFingerprint(fp)); \
88 assembler->Comment("Intrinsic"); \ 186 compiler->assembler()->Comment("Intrinsic"); \
89 enum_name(assembler); \ 187 enum_name(compiler->assembler()); \
90 break; 188 break;
91 189
92 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32)) { 190 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32)) {
93 // Integer intrinsics are in the core library, but we don't want to 191 // Integer intrinsics are in the core library, but we don't want to
94 // intrinsify when Smi > 32 bits if we are looking for javascript integer 192 // intrinsify when Smi > 32 bits if we are looking for javascript integer
95 // overflow. 193 // overflow.
96 switch (function.recognized_kind()) { 194 switch (function.recognized_kind()) {
97 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); 195 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE);
98 MATH_LIB_INTRINSIC_LIST(EMIT_CASE);
99 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE);
100 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE);
101 default: 196 default:
102 break; 197 break;
103 } 198 }
104 } else { 199 } else {
105 switch (function.recognized_kind()) { 200 switch (function.recognized_kind()) {
106 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); 201 ALL_INTRINSICS_LIST(EMIT_CASE);
107 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE);
108 MATH_LIB_INTRINSIC_LIST(EMIT_CASE);
109 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE);
110 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE);
111 default: 202 default:
112 UNREACHABLE(); 203 UNREACHABLE();
113 break; 204 break;
114 } 205 }
115 } 206 }
116 #undef EMIT_INTRINSIC 207 #undef EMIT_INTRINSIC
117 } 208 }
118 209
210
211 class BlockBuilder : public ValueObject {
212 public:
213 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry)
214 : flow_graph_(flow_graph), entry_(entry), current_(entry) { }
215
216 Definition* AddToInitialDefinitions(Definition* def) {
217 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
218 flow_graph_->AddToInitialDefinitions(def);
219 return def;
220 }
221
222 Definition* AddDefinition(Definition* def) {
223 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
224 current_ = current_->AppendInstruction(def);
225 return def;
226 }
227
228 Instruction* AddInstruction(Instruction* instr) {
229 current_ = current_->AppendInstruction(instr);
230 return instr;
231 }
232
233 void AddIntrinsicReturn(Value* value) {
234 ReturnInstr* instr = new ReturnInstr(-1, // No token position.
235 value);
236 AddInstruction(instr);
237 entry_->set_last_instruction(instr);
238 }
239
240 Definition* AddParameter(intptr_t index) {
241 intptr_t adjustment = Intrinsifier::ParameterSlotFromSp();
242 return AddToInitialDefinitions(
243 new ParameterInstr(adjustment + index,
244 flow_graph_->graph_entry(),
245 SPREG));
246 }
247
248
249 private:
250 FlowGraph* flow_graph_;
251 BlockEntryInstr* entry_;
252 Instruction* current_;
253 };
254
255
256 static void PrepareIndexedOp(BlockBuilder* builder,
257 Definition* array,
258 Definition* index,
259 intptr_t length_offset) {
260 builder->AddInstruction(
261 new CheckSmiInstr(new Value(index),
262 Isolate::kNoDeoptId,
263 -1)); // no token pos
264
265 Definition* length = builder->AddDefinition(
266 new LoadFieldInstr(new Value(array),
267 length_offset,
268 Type::ZoneHandle(Type::SmiType()),
269 true)); // immutable
270 builder->AddInstruction(
271 new CheckArrayBoundInstr(new Value(length),
272 new Value(index),
273 Isolate::kNoDeoptId));
274 }
275
276
277 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) {
278 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
279 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
280 BlockBuilder builder(flow_graph, normal_entry);
281
282 Definition* index = builder.AddParameter(1);
283 Definition* array = builder.AddParameter(2);
284
285 PrepareIndexedOp(&builder, array, index, Array::length_offset());
286
287 Definition* result = builder.AddDefinition(
288 new LoadIndexedInstr(new Value(array),
289 new Value(index),
290 Instance::ElementSizeFor(kArrayCid), // index scale
291 kArrayCid,
292 Isolate::kNoDeoptId,
293 -1)); // no token pos
294 builder.AddIntrinsicReturn(new Value(result));
295 return true;
296 }
297
298
299 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
300 return Build_ObjectArrayGetIndexed(flow_graph);
301 }
302
303
304 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
305 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
306 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
307 BlockBuilder builder(flow_graph, normal_entry);
308
309 Definition* index = builder.AddParameter(1);
310 Definition* array = builder.AddParameter(2);
311
312 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
313
314 Definition* result = builder.AddDefinition(
315 new LoadIndexedInstr(new Value(array),
316 new Value(index),
317 1, // index scale
318 kTypedDataUint8ArrayCid,
319 Isolate::kNoDeoptId,
320 -1)); // no token pos
321 builder.AddIntrinsicReturn(new Value(result));
322 return true;
323 }
324
325
326 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) {
327 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
328 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
329 BlockBuilder builder(flow_graph, normal_entry);
330
331 Definition* index = builder.AddParameter(1);
332 Definition* array = builder.AddParameter(2);
333
334 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
335
336 Definition* elements = builder.AddDefinition(
337 new LoadUntaggedInstr(new Value(array),
338 ExternalTypedData::data_offset()));
339 Definition* result = builder.AddDefinition(
340 new LoadIndexedInstr(new Value(elements),
341 new Value(index),
342 1, // index scale
343 kExternalTypedDataUint8ArrayCid,
344 Isolate::kNoDeoptId,
345 -1)); // no token pos
346 builder.AddIntrinsicReturn(new Value(result));
347 return true;
348 }
349
350
351 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
352 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
353 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
354 BlockBuilder builder(flow_graph, normal_entry);
355
356 Definition* value = builder.AddParameter(1);
357 Definition* index = builder.AddParameter(2);
358 Definition* array = builder.AddParameter(3);
359
360 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
361
362 builder.AddInstruction(
363 new CheckSmiInstr(new Value(value),
364 Isolate::kNoDeoptId,
365 -1)); // no token pos
366
367 builder.AddInstruction(
368 new StoreIndexedInstr(new Value(array),
369 new Value(index),
370 new Value(value),
371 kNoStoreBarrier,
372 1, // index scale
373 kTypedDataUint8ArrayCid,
374 Isolate::kNoDeoptId,
375 -1)); // no token pos.
376 // Return null.
377 Definition* null_def = builder.AddDefinition(
378 new ConstantInstr(Object::ZoneHandle(Object::null())));
379 builder.AddIntrinsicReturn(new Value(null_def));
380 return true;
381 }
382
383
384 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
385 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
386 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
387 BlockBuilder builder(flow_graph, normal_entry);
388
389 Definition* value = builder.AddParameter(1);
390 Definition* index = builder.AddParameter(2);
391 Definition* array = builder.AddParameter(3);
392
393 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
394
395 builder.AddInstruction(
396 new CheckSmiInstr(new Value(value),
397 Isolate::kNoDeoptId,
398 -1)); // no token pos
399 Definition* elements = builder.AddDefinition(
400 new LoadUntaggedInstr(new Value(array),
401 ExternalTypedData::data_offset()));
402 builder.AddInstruction(
403 new StoreIndexedInstr(new Value(elements),
404 new Value(index),
405 new Value(value),
406 kNoStoreBarrier,
407 1, // index scale
408 kExternalTypedDataUint8ArrayCid,
409 Isolate::kNoDeoptId,
410 -1)); // no token pos.
411 // Return null.
412 Definition* null_def = builder.AddDefinition(
413 new ConstantInstr(Object::ZoneHandle(Object::null())));
414 builder.AddIntrinsicReturn(new Value(null_def));
415 return true;
416 }
417
418
419 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
420 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
421
422 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
423 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
424 BlockBuilder builder(flow_graph, normal_entry);
425
426 Definition* value = builder.AddParameter(1);
427 Definition* index = builder.AddParameter(2);
428 Definition* array = builder.AddParameter(3);
429
430 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
431
432 const ICData& value_check = ICData::ZoneHandle(ICData::New(
433 flow_graph->parsed_function().function(),
434 String::Handle(flow_graph->parsed_function().function().name()),
435 Object::empty_array(), // Dummy args. descr.
436 Isolate::kNoDeoptId,
437 1));
438 value_check.AddReceiverCheck(kDoubleCid,
439 flow_graph->parsed_function().function());
440 builder.AddInstruction(
441 new CheckClassInstr(new Value(value),
442 Isolate::kNoDeoptId,
443 value_check,
444 -1));
445 Definition* double_value = builder.AddDefinition(
446 new UnboxDoubleInstr(new Value(value), Isolate::kNoDeoptId));
447 // Manually adjust reaching type because there is no type propagation
448 // when building intrinsics.
449 double_value->AsUnboxDouble()->value()->SetReachingType(
450 ZoneCompileType::Wrap(CompileType::FromCid(kDoubleCid)));
451
452 builder.AddInstruction(
453 new StoreIndexedInstr(new Value(array),
454 new Value(index),
455 new Value(double_value),
456 kNoStoreBarrier,
457 8, // index scale
458 kTypedDataFloat64ArrayCid,
459 Isolate::kNoDeoptId,
460 -1)); // no token pos.
461 // Return null.
462 Definition* null_def = builder.AddDefinition(
463 new ConstantInstr(Object::ZoneHandle(Object::null())));
464 builder.AddIntrinsicReturn(new Value(null_def));
465 return true;
466 }
467
468
469 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
470 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
471
472 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
473 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
474 BlockBuilder builder(flow_graph, normal_entry);
475
476 Definition* index = builder.AddParameter(1);
477 Definition* array = builder.AddParameter(2);
478
479 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
480
481 Definition* unboxed_value = builder.AddDefinition(
482 new LoadIndexedInstr(new Value(array),
483 new Value(index),
484 8, // index scale
485 kTypedDataFloat64ArrayCid,
486 Isolate::kNoDeoptId,
487 -1)); // no token pos
488 Definition* result = builder.AddDefinition(
489 new BoxDoubleInstr(new Value(unboxed_value)));
490 builder.AddIntrinsicReturn(new Value(result));
491 return true;
492 }
493
494
495 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) {
496 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
497 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
498 BlockBuilder builder(flow_graph, normal_entry);
499
500 Definition* array = builder.AddParameter(1);
501
502 Definition* length = builder.AddDefinition(
503 new LoadFieldInstr(new Value(array),
504 offset,
505 Type::ZoneHandle(),
506 -1)); // No token pos
507 builder.AddIntrinsicReturn(new Value(length));
508 return true;
509 }
510
511
512 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) {
513 return BuildLoadField(flow_graph, Array::length_offset());
514 }
515
516
517 bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) {
518 return BuildLoadField(flow_graph, Array::length_offset());
519 }
520
521
522 bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
523 return BuildLoadField(flow_graph, GrowableObjectArray::length_offset());
524 }
525
526
527 bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
528 return BuildLoadField(flow_graph, String::length_offset());
529 }
530
531
532 bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) {
533 return BuildLoadField(flow_graph, TypedData::length_offset());
534 }
535
536
537 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
538 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
539 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
540 BlockBuilder builder(flow_graph, normal_entry);
541
542 Definition* array = builder.AddParameter(1);
543
544 Definition* backing_store = builder.AddDefinition(
545 new LoadFieldInstr(new Value(array),
546 GrowableObjectArray::data_offset(),
547 Type::ZoneHandle(),
548 -1)); // No token pos
549 Definition* capacity = builder.AddDefinition(
550 new LoadFieldInstr(new Value(backing_store),
551 Array::length_offset(),
552 Type::ZoneHandle(),
553 -1)); // No token pos
554 builder.AddIntrinsicReturn(new Value(capacity));
555 return true;
556 }
557
558
119 } // namespace dart 559 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698