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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 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
« no previous file with comments | « runtime/vm/regexp_assembler_ir.h ('k') | runtime/vm/regexp_ast.h » ('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 (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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/regexp_assembler_ir.h" 5 #include "vm/regexp_assembler_ir.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 22 matching lines...) Expand all
33 #define PRINT(arg) \ 33 #define PRINT(arg) \
34 if (FLAG_trace_irregexp) { \ 34 if (FLAG_trace_irregexp) { \
35 Print(arg); \ 35 Print(arg); \
36 } 36 }
37 37
38 namespace dart { 38 namespace dart {
39 39
40 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex; 40 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
41 static const intptr_t kMinStackSize = 512; 41 static const intptr_t kMinStackSize = 512;
42 42
43
44 /* 43 /*
45 * This assembler uses the following main local variables: 44 * This assembler uses the following main local variables:
46 * - stack_: A pointer to a growable list which we use as an all-purpose stack 45 * - stack_: A pointer to a growable list which we use as an all-purpose stack
47 * storing backtracking offsets, positions & stored register values. 46 * storing backtracking offsets, positions & stored register values.
48 * - current_character_: Stores the currently loaded characters (possibly more 47 * - current_character_: Stores the currently loaded characters (possibly more
49 * than one). 48 * than one).
50 * - current_position_: The current position within the string, stored as a 49 * - current_position_: The current position within the string, stored as a
51 * negative offset from the end of the string (i.e. the 50 * negative offset from the end of the string (i.e. the
52 * position corresponding to str[0] is -str.length). 51 * position corresponding to str[0] is -str.length).
53 * Note that current_position_ is *not* byte-based, unlike 52 * Note that current_position_ is *not* byte-based, unlike
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 blocks_.Add(entry_block_->normal_entry()); 134 blocks_.Add(entry_block_->normal_entry());
136 blocks_.Add(start_block_); 135 blocks_.Add(start_block_);
137 blocks_.Add(success_block_); 136 blocks_.Add(success_block_);
138 blocks_.Add(backtrack_block_); 137 blocks_.Add(backtrack_block_);
139 blocks_.Add(exit_block_); 138 blocks_.Add(exit_block_);
140 139
141 // Begin emission at the start_block_. 140 // Begin emission at the start_block_.
142 set_current_instruction(start_block_); 141 set_current_instruction(start_block_);
143 } 142 }
144 143
145
146 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() {} 144 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() {}
147 145
148
149 void IRRegExpMacroAssembler::InitializeLocals() { 146 void IRRegExpMacroAssembler::InitializeLocals() {
150 // All generated functions are expected to have a current-context variable. 147 // All generated functions are expected to have a current-context variable.
151 // This variable is unused in irregexp functions. 148 // This variable is unused in irregexp functions.
152 parsed_function_->current_context_var()->set_index(GetNextLocalIndex()); 149 parsed_function_->current_context_var()->set_index(GetNextLocalIndex());
153 150
154 // Create local variables and parameters. 151 // Create local variables and parameters.
155 stack_ = Local(Symbols::stack()); 152 stack_ = Local(Symbols::stack());
156 stack_pointer_ = Local(Symbols::stack_pointer()); 153 stack_pointer_ = Local(Symbols::stack_pointer());
157 registers_ = Local(Symbols::position_registers()); 154 registers_ = Local(Symbols::position_registers());
158 current_character_ = Local(Symbols::current_character()); 155 current_character_ = Local(Symbols::current_character());
159 current_position_ = Local(Symbols::current_position()); 156 current_position_ = Local(Symbols::current_position());
160 string_param_length_ = Local(Symbols::string_param_length()); 157 string_param_length_ = Local(Symbols::string_param_length());
161 capture_length_ = Local(Symbols::capture_length()); 158 capture_length_ = Local(Symbols::capture_length());
162 match_start_index_ = Local(Symbols::match_start_index()); 159 match_start_index_ = Local(Symbols::match_start_index());
163 capture_start_index_ = Local(Symbols::capture_start_index()); 160 capture_start_index_ = Local(Symbols::capture_start_index());
164 match_end_index_ = Local(Symbols::match_end_index()); 161 match_end_index_ = Local(Symbols::match_end_index());
165 char_in_capture_ = Local(Symbols::char_in_capture()); 162 char_in_capture_ = Local(Symbols::char_in_capture());
166 char_in_match_ = Local(Symbols::char_in_match()); 163 char_in_match_ = Local(Symbols::char_in_match());
167 index_temp_ = Local(Symbols::index_temp()); 164 index_temp_ = Local(Symbols::index_temp());
168 result_ = Local(Symbols::result()); 165 result_ = Local(Symbols::result());
169 166
170 string_param_ = Parameter(Symbols::string_param(), 167 string_param_ = Parameter(Symbols::string_param(),
171 RegExpMacroAssembler::kParamStringIndex); 168 RegExpMacroAssembler::kParamStringIndex);
172 start_index_param_ = Parameter(Symbols::start_index_param(), 169 start_index_param_ = Parameter(Symbols::start_index_param(),
173 RegExpMacroAssembler::kParamStartOffsetIndex); 170 RegExpMacroAssembler::kParamStartOffsetIndex);
174 } 171 }
175 172
176
177 void IRRegExpMacroAssembler::GenerateEntryBlock() { 173 void IRRegExpMacroAssembler::GenerateEntryBlock() {
178 set_current_instruction(entry_block_->normal_entry()); 174 set_current_instruction(entry_block_->normal_entry());
179 TAG(); 175 TAG();
180 176
181 // Store string.length. 177 // Store string.length.
182 PushArgumentInstr* string_push = PushLocal(string_param_); 178 PushArgumentInstr* string_push = PushLocal(string_param_);
183 179
184 StoreLocal(string_param_length_, 180 StoreLocal(string_param_length_,
185 Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle( 181 Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle(
186 Field::GetterSymbol(Symbols::Length()))), 182 Field::GetterSymbol(Symbols::Length()))),
(...skipping 17 matching lines...) Expand all
204 StoreLocal(stack_, 200 StoreLocal(stack_,
205 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 201 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
206 stack_cell_push, 202 stack_cell_push,
207 PushArgument(Bind(Uint64Constant(0)))))); 203 PushArgument(Bind(Uint64Constant(0))))));
208 StoreLocal(stack_pointer_, Bind(Int64Constant(-1))); 204 StoreLocal(stack_pointer_, Bind(Int64Constant(-1)));
209 205
210 // Jump to the start block. 206 // Jump to the start block.
211 current_instruction_->Goto(start_block_); 207 current_instruction_->Goto(start_block_);
212 } 208 }
213 209
214
215 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { 210 void IRRegExpMacroAssembler::GenerateBacktrackBlock() {
216 set_current_instruction(backtrack_block_); 211 set_current_instruction(backtrack_block_);
217 TAG(); 212 TAG();
218 CheckPreemption(/*is_backtrack=*/true); 213 CheckPreemption(/*is_backtrack=*/true);
219 214
220 const intptr_t entries_count = entry_block_->indirect_entries().length(); 215 const intptr_t entries_count = entry_block_->indirect_entries().length();
221 216
222 TypedData& offsets = TypedData::ZoneHandle( 217 TypedData& offsets = TypedData::ZoneHandle(
223 Z, TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld)); 218 Z, TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld));
224 219
225 PushArgumentInstr* block_offsets_push = 220 PushArgumentInstr* block_offsets_push =
226 PushArgument(Bind(new (Z) ConstantInstr(offsets))); 221 PushArgument(Bind(new (Z) ConstantInstr(offsets)));
227 PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack())); 222 PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack()));
228 223
229 Value* offset_value = 224 Value* offset_value =
230 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 225 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
231 block_offsets_push, block_id_push)); 226 block_offsets_push, block_id_push));
232 227
233 backtrack_goto_ = new (Z) IndirectGotoInstr(&offsets, offset_value); 228 backtrack_goto_ = new (Z) IndirectGotoInstr(&offsets, offset_value);
234 CloseBlockWith(backtrack_goto_); 229 CloseBlockWith(backtrack_goto_);
235 230
236 // Add an edge from the "indirect" goto to each of the targets. 231 // Add an edge from the "indirect" goto to each of the targets.
237 for (intptr_t j = 0; j < entries_count; j++) { 232 for (intptr_t j = 0; j < entries_count; j++) {
238 backtrack_goto_->AddSuccessor( 233 backtrack_goto_->AddSuccessor(
239 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); 234 TargetWithJoinGoto(entry_block_->indirect_entries().At(j)));
240 } 235 }
241 } 236 }
242 237
243
244 void IRRegExpMacroAssembler::GenerateSuccessBlock() { 238 void IRRegExpMacroAssembler::GenerateSuccessBlock() {
245 set_current_instruction(success_block_); 239 set_current_instruction(success_block_);
246 TAG(); 240 TAG();
247 241
248 Value* type = Bind(new (Z) ConstantInstr( 242 Value* type = Bind(new (Z) ConstantInstr(
249 TypeArguments::ZoneHandle(Z, TypeArguments::null()))); 243 TypeArguments::ZoneHandle(Z, TypeArguments::null())));
250 Value* length = Bind(Uint64Constant(saved_registers_count_)); 244 Value* length = Bind(Uint64Constant(saved_registers_count_));
251 Value* array = Bind(new (Z) CreateArrayInstr(TokenPosition::kNoSource, type, 245 Value* array = Bind(new (Z) CreateArrayInstr(TokenPosition::kNoSource, type,
252 length, GetNextDeoptId())); 246 length, GetNextDeoptId()));
253 StoreLocal(result_, array); 247 StoreLocal(result_, array);
(...skipping 15 matching lines...) Expand all
269 } 263 }
270 264
271 // Print the result if tracing. 265 // Print the result if tracing.
272 PRINT(PushLocal(result_)); 266 PRINT(PushLocal(result_));
273 267
274 // Return true on success. 268 // Return true on success.
275 AppendInstruction(new (Z) ReturnInstr( 269 AppendInstruction(new (Z) ReturnInstr(
276 TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId())); 270 TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
277 } 271 }
278 272
279
280 void IRRegExpMacroAssembler::GenerateExitBlock() { 273 void IRRegExpMacroAssembler::GenerateExitBlock() {
281 set_current_instruction(exit_block_); 274 set_current_instruction(exit_block_);
282 TAG(); 275 TAG();
283 276
284 // Return false on failure. 277 // Return false on failure.
285 AppendInstruction(new (Z) ReturnInstr( 278 AppendInstruction(new (Z) ReturnInstr(
286 TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId())); 279 TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
287 } 280 }
288 281
289
290 void IRRegExpMacroAssembler::FinalizeRegistersArray() { 282 void IRRegExpMacroAssembler::FinalizeRegistersArray() {
291 ASSERT(registers_count_ >= saved_registers_count_); 283 ASSERT(registers_count_ >= saved_registers_count_);
292 registers_array_ = 284 registers_array_ =
293 TypedData::New(kTypedDataInt32ArrayCid, registers_count_, Heap::kOld); 285 TypedData::New(kTypedDataInt32ArrayCid, registers_count_, Heap::kOld);
294 } 286 }
295 287
296
297 #if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) 288 #if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM)
298 // Disabling unaligned accesses forces the regexp engine to load characters one 289 // Disabling unaligned accesses forces the regexp engine to load characters one
299 // by one instead of up to 4 at once, along with the associated performance hit. 290 // by one instead of up to 4 at once, along with the associated performance hit.
300 // TODO(zerny): Be less conservative about disabling unaligned accesses. 291 // TODO(zerny): Be less conservative about disabling unaligned accesses.
301 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here, 292 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here,
302 // update LoadCodeUnitsInstr methods for the appropriate architectures. 293 // update LoadCodeUnitsInstr methods for the appropriate architectures.
303 static const bool kEnableUnalignedAccesses = false; 294 static const bool kEnableUnalignedAccesses = false;
304 #else 295 #else
305 static const bool kEnableUnalignedAccesses = true; 296 static const bool kEnableUnalignedAccesses = true;
306 #endif 297 #endif
307 bool IRRegExpMacroAssembler::CanReadUnaligned() { 298 bool IRRegExpMacroAssembler::CanReadUnaligned() {
308 return kEnableUnalignedAccesses && !slow_safe(); 299 return kEnableUnalignedAccesses && !slow_safe();
309 } 300 }
310 301
311
312 RawArray* IRRegExpMacroAssembler::Execute(const RegExp& regexp, 302 RawArray* IRRegExpMacroAssembler::Execute(const RegExp& regexp,
313 const String& input, 303 const String& input,
314 const Smi& start_offset, 304 const Smi& start_offset,
315 bool sticky, 305 bool sticky,
316 Zone* zone) { 306 Zone* zone) {
317 const intptr_t cid = input.GetClassId(); 307 const intptr_t cid = input.GetClassId();
318 const Function& fun = Function::Handle(regexp.function(cid, sticky)); 308 const Function& fun = Function::Handle(regexp.function(cid, sticky));
319 ASSERT(!fun.IsNull()); 309 ASSERT(!fun.IsNull());
320 // Create the argument list. 310 // Create the argument list.
321 const Array& args = 311 const Array& args =
(...skipping 14 matching lines...) Expand all
336 } 326 }
337 327
338 if (retval.IsNull()) { 328 if (retval.IsNull()) {
339 return Array::null(); 329 return Array::null();
340 } 330 }
341 331
342 ASSERT(retval.IsArray()); 332 ASSERT(retval.IsArray());
343 return Array::Cast(retval).raw(); 333 return Array::Cast(retval).raw();
344 } 334 }
345 335
346
347 LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name, 336 LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
348 intptr_t index) const { 337 intptr_t index) const {
349 LocalVariable* local = 338 LocalVariable* local =
350 new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, 339 new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
351 name, Object::dynamic_type()); 340 name, Object::dynamic_type());
352 341
353 intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index; 342 intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index;
354 local->set_index(param_frame_index); 343 local->set_index(param_frame_index);
355 344
356 return local; 345 return local;
357 } 346 }
358 347
359
360 LocalVariable* IRRegExpMacroAssembler::Local(const String& name) { 348 LocalVariable* IRRegExpMacroAssembler::Local(const String& name) {
361 LocalVariable* local = 349 LocalVariable* local =
362 new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, 350 new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
363 name, Object::dynamic_type()); 351 name, Object::dynamic_type());
364 local->set_index(GetNextLocalIndex()); 352 local->set_index(GetNextLocalIndex());
365 353
366 return local; 354 return local;
367 } 355 }
368 356
369
370 ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const { 357 ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const {
371 return new (Z) 358 return new (Z)
372 ConstantInstr(Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld))); 359 ConstantInstr(Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld)));
373 } 360 }
374 361
375
376 ConstantInstr* IRRegExpMacroAssembler::Uint64Constant(uint64_t value) const { 362 ConstantInstr* IRRegExpMacroAssembler::Uint64Constant(uint64_t value) const {
377 return new (Z) ConstantInstr( 363 return new (Z) ConstantInstr(
378 Integer::ZoneHandle(Z, Integer::NewFromUint64(value, Heap::kOld))); 364 Integer::ZoneHandle(Z, Integer::NewFromUint64(value, Heap::kOld)));
379 } 365 }
380 366
381
382 ConstantInstr* IRRegExpMacroAssembler::BoolConstant(bool value) const { 367 ConstantInstr* IRRegExpMacroAssembler::BoolConstant(bool value) const {
383 return new (Z) ConstantInstr(value ? Bool::True() : Bool::False()); 368 return new (Z) ConstantInstr(value ? Bool::True() : Bool::False());
384 } 369 }
385 370
386
387 ConstantInstr* IRRegExpMacroAssembler::StringConstant(const char* value) const { 371 ConstantInstr* IRRegExpMacroAssembler::StringConstant(const char* value) const {
388 return new (Z) 372 return new (Z)
389 ConstantInstr(String::ZoneHandle(Z, String::New(value, Heap::kOld))); 373 ConstantInstr(String::ZoneHandle(Z, String::New(value, Heap::kOld)));
390 } 374 }
391 375
392
393 ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const { 376 ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const {
394 const Library& lib = Library::Handle(Z, Library::CoreLibrary()); 377 const Library& lib = Library::Handle(Z, Library::CoreLibrary());
395 const Class& regexp_class = 378 const Class& regexp_class =
396 Class::Handle(Z, lib.LookupClassAllowPrivate(Symbols::_RegExp())); 379 Class::Handle(Z, lib.LookupClassAllowPrivate(Symbols::_RegExp()));
397 const Field& word_character_field = Field::ZoneHandle( 380 const Field& word_character_field = Field::ZoneHandle(
398 Z, 381 Z,
399 regexp_class.LookupStaticFieldAllowPrivate(Symbols::_wordCharacterMap())); 382 regexp_class.LookupStaticFieldAllowPrivate(Symbols::_wordCharacterMap()));
400 ASSERT(!word_character_field.IsNull()); 383 ASSERT(!word_character_field.IsNull());
401 384
402 if (word_character_field.IsUninitialized()) { 385 if (word_character_field.IsUninitialized()) {
403 ASSERT(!Compiler::IsBackgroundCompilation()); 386 ASSERT(!Compiler::IsBackgroundCompilation());
404 word_character_field.EvaluateInitializer(); 387 word_character_field.EvaluateInitializer();
405 } 388 }
406 ASSERT(!word_character_field.IsUninitialized()); 389 ASSERT(!word_character_field.IsUninitialized());
407 390
408 return new (Z) ConstantInstr( 391 return new (Z) ConstantInstr(
409 Instance::ZoneHandle(Z, word_character_field.StaticValue())); 392 Instance::ZoneHandle(Z, word_character_field.StaticValue()));
410 } 393 }
411 394
412
413 ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind, 395 ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
414 PushArgumentInstr* lhs, 396 PushArgumentInstr* lhs,
415 PushArgumentInstr* rhs) { 397 PushArgumentInstr* rhs) {
416 Token::Kind strict_comparison = Token::kEQ_STRICT; 398 Token::Kind strict_comparison = Token::kEQ_STRICT;
417 Token::Kind intermediate_operator = Token::kILLEGAL; 399 Token::Kind intermediate_operator = Token::kILLEGAL;
418 switch (kind) { 400 switch (kind) {
419 case kEQ: 401 case kEQ:
420 intermediate_operator = Token::kEQ; 402 intermediate_operator = Token::kEQ;
421 break; 403 break;
422 case kNE: 404 case kNE:
(...skipping 28 matching lines...) Expand all
451 } 433 }
452 434
453 ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind, 435 ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
454 Definition* lhs, 436 Definition* lhs,
455 Definition* rhs) { 437 Definition* rhs) {
456 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs)); 438 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs));
457 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs)); 439 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs));
458 return Comparison(kind, lhs_push, rhs_push); 440 return Comparison(kind, lhs_push, rhs_push);
459 } 441 }
460 442
461
462 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 443 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
463 const Function& function) const { 444 const Function& function) const {
464 ZoneGrowableArray<PushArgumentInstr*>* arguments = 445 ZoneGrowableArray<PushArgumentInstr*>* arguments =
465 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); 446 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
466 return StaticCall(function, arguments); 447 return StaticCall(function, arguments);
467 } 448 }
468 449
469
470 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 450 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
471 const Function& function, 451 const Function& function,
472 PushArgumentInstr* arg1) const { 452 PushArgumentInstr* arg1) const {
473 ZoneGrowableArray<PushArgumentInstr*>* arguments = 453 ZoneGrowableArray<PushArgumentInstr*>* arguments =
474 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); 454 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
475 arguments->Add(arg1); 455 arguments->Add(arg1);
476 456
477 return StaticCall(function, arguments); 457 return StaticCall(function, arguments);
478 } 458 }
479 459
480
481 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 460 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
482 const Function& function, 461 const Function& function,
483 PushArgumentInstr* arg1, 462 PushArgumentInstr* arg1,
484 PushArgumentInstr* arg2) const { 463 PushArgumentInstr* arg2) const {
485 ZoneGrowableArray<PushArgumentInstr*>* arguments = 464 ZoneGrowableArray<PushArgumentInstr*>* arguments =
486 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); 465 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
487 arguments->Add(arg1); 466 arguments->Add(arg1);
488 arguments->Add(arg2); 467 arguments->Add(arg2);
489 468
490 return StaticCall(function, arguments); 469 return StaticCall(function, arguments);
491 } 470 }
492 471
493
494 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 472 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
495 const Function& function, 473 const Function& function,
496 ZoneGrowableArray<PushArgumentInstr*>* arguments) const { 474 ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
497 const intptr_t kTypeArgsLen = 0; 475 const intptr_t kTypeArgsLen = 0;
498 return new (Z) StaticCallInstr(TokenPosition::kNoSource, function, 476 return new (Z) StaticCallInstr(TokenPosition::kNoSource, function,
499 kTypeArgsLen, Object::null_array(), arguments, 477 kTypeArgsLen, Object::null_array(), arguments,
500 ic_data_array_, GetNextDeoptId()); 478 ic_data_array_, GetNextDeoptId());
501 } 479 }
502 480
503
504 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 481 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
505 const InstanceCallDescriptor& desc, 482 const InstanceCallDescriptor& desc,
506 PushArgumentInstr* arg1) const { 483 PushArgumentInstr* arg1) const {
507 ZoneGrowableArray<PushArgumentInstr*>* arguments = 484 ZoneGrowableArray<PushArgumentInstr*>* arguments =
508 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); 485 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
509 arguments->Add(arg1); 486 arguments->Add(arg1);
510 487
511 return InstanceCall(desc, arguments); 488 return InstanceCall(desc, arguments);
512 } 489 }
513 490
514
515 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 491 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
516 const InstanceCallDescriptor& desc, 492 const InstanceCallDescriptor& desc,
517 PushArgumentInstr* arg1, 493 PushArgumentInstr* arg1,
518 PushArgumentInstr* arg2) const { 494 PushArgumentInstr* arg2) const {
519 ZoneGrowableArray<PushArgumentInstr*>* arguments = 495 ZoneGrowableArray<PushArgumentInstr*>* arguments =
520 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); 496 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
521 arguments->Add(arg1); 497 arguments->Add(arg1);
522 arguments->Add(arg2); 498 arguments->Add(arg2);
523 499
524 return InstanceCall(desc, arguments); 500 return InstanceCall(desc, arguments);
525 } 501 }
526 502
527
528 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 503 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
529 const InstanceCallDescriptor& desc, 504 const InstanceCallDescriptor& desc,
530 PushArgumentInstr* arg1, 505 PushArgumentInstr* arg1,
531 PushArgumentInstr* arg2, 506 PushArgumentInstr* arg2,
532 PushArgumentInstr* arg3) const { 507 PushArgumentInstr* arg3) const {
533 ZoneGrowableArray<PushArgumentInstr*>* arguments = 508 ZoneGrowableArray<PushArgumentInstr*>* arguments =
534 new (Z) ZoneGrowableArray<PushArgumentInstr*>(3); 509 new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
535 arguments->Add(arg1); 510 arguments->Add(arg1);
536 arguments->Add(arg2); 511 arguments->Add(arg2);
537 arguments->Add(arg3); 512 arguments->Add(arg3);
538 513
539 return InstanceCall(desc, arguments); 514 return InstanceCall(desc, arguments);
540 } 515 }
541 516
542
543 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 517 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
544 const InstanceCallDescriptor& desc, 518 const InstanceCallDescriptor& desc,
545 ZoneGrowableArray<PushArgumentInstr*>* arguments) const { 519 ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
546 const intptr_t kTypeArgsLen = 0; 520 const intptr_t kTypeArgsLen = 0;
547 return new (Z) InstanceCallInstr( 521 return new (Z) InstanceCallInstr(
548 TokenPosition::kNoSource, desc.name, desc.token_kind, arguments, 522 TokenPosition::kNoSource, desc.name, desc.token_kind, arguments,
549 kTypeArgsLen, Object::null_array(), desc.checked_argument_count, 523 kTypeArgsLen, Object::null_array(), desc.checked_argument_count,
550 ic_data_array_, GetNextDeoptId()); 524 ic_data_array_, GetNextDeoptId());
551 } 525 }
552 526
553
554 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const { 527 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const {
555 return new (Z) LoadLocalInstr(*local, TokenPosition::kNoSource); 528 return new (Z) LoadLocalInstr(*local, TokenPosition::kNoSource);
556 } 529 }
557 530
558
559 void IRRegExpMacroAssembler::StoreLocal(LocalVariable* local, Value* value) { 531 void IRRegExpMacroAssembler::StoreLocal(LocalVariable* local, Value* value) {
560 Do(new (Z) StoreLocalInstr(*local, value, TokenPosition::kNoSource)); 532 Do(new (Z) StoreLocalInstr(*local, value, TokenPosition::kNoSource));
561 } 533 }
562 534
563
564 void IRRegExpMacroAssembler::set_current_instruction(Instruction* instruction) { 535 void IRRegExpMacroAssembler::set_current_instruction(Instruction* instruction) {
565 current_instruction_ = instruction; 536 current_instruction_ = instruction;
566 } 537 }
567 538
568
569 Value* IRRegExpMacroAssembler::Bind(Definition* definition) { 539 Value* IRRegExpMacroAssembler::Bind(Definition* definition) {
570 AppendInstruction(definition); 540 AppendInstruction(definition);
571 definition->set_temp_index(temp_id_.Alloc()); 541 definition->set_temp_index(temp_id_.Alloc());
572 542
573 return new (Z) Value(definition); 543 return new (Z) Value(definition);
574 } 544 }
575 545
576
577 void IRRegExpMacroAssembler::Do(Definition* definition) { 546 void IRRegExpMacroAssembler::Do(Definition* definition) {
578 AppendInstruction(definition); 547 AppendInstruction(definition);
579 } 548 }
580 549
581
582 Value* IRRegExpMacroAssembler::BindLoadLocal(const LocalVariable& local) { 550 Value* IRRegExpMacroAssembler::BindLoadLocal(const LocalVariable& local) {
583 if (local.IsConst()) { 551 if (local.IsConst()) {
584 return Bind(new (Z) ConstantInstr(*local.ConstValue())); 552 return Bind(new (Z) ConstantInstr(*local.ConstValue()));
585 } 553 }
586 ASSERT(!local.is_captured()); 554 ASSERT(!local.is_captured());
587 return Bind(new (Z) LoadLocalInstr(local, TokenPosition::kNoSource)); 555 return Bind(new (Z) LoadLocalInstr(local, TokenPosition::kNoSource));
588 } 556 }
589 557
590
591 // In some cases, the V8 irregexp engine generates unreachable code by emitting 558 // In some cases, the V8 irregexp engine generates unreachable code by emitting
592 // a jmp not followed by a bind. We cannot do the same, since it is impossible 559 // a jmp not followed by a bind. We cannot do the same, since it is impossible
593 // to append to a block following a jmp. In such cases, assume that we are doing 560 // to append to a block following a jmp. In such cases, assume that we are doing
594 // the correct thing, but output a warning when tracing. 561 // the correct thing, but output a warning when tracing.
595 #define HANDLE_DEAD_CODE_EMISSION() \ 562 #define HANDLE_DEAD_CODE_EMISSION() \
596 if (current_instruction_ == NULL) { \ 563 if (current_instruction_ == NULL) { \
597 if (FLAG_trace_irregexp) { \ 564 if (FLAG_trace_irregexp) { \
598 OS::Print( \ 565 OS::Print( \
599 "WARNING: Attempting to append to a closed assembler. " \ 566 "WARNING: Attempting to append to a closed assembler. " \
600 "This could be either a bug or generation of dead code " \ 567 "This could be either a bug or generation of dead code " \
601 "inherited from V8.\n"); \ 568 "inherited from V8.\n"); \
602 } \ 569 } \
603 BlockLabel dummy; \ 570 BlockLabel dummy; \
604 BindBlock(&dummy); \ 571 BindBlock(&dummy); \
605 } 572 }
606 573
607 void IRRegExpMacroAssembler::AppendInstruction(Instruction* instruction) { 574 void IRRegExpMacroAssembler::AppendInstruction(Instruction* instruction) {
608 HANDLE_DEAD_CODE_EMISSION(); 575 HANDLE_DEAD_CODE_EMISSION();
609 576
610 ASSERT(current_instruction_ != NULL); 577 ASSERT(current_instruction_ != NULL);
611 ASSERT(current_instruction_->next() == NULL); 578 ASSERT(current_instruction_->next() == NULL);
612 579
613 temp_id_.Dealloc(instruction->InputCount()); 580 temp_id_.Dealloc(instruction->InputCount());
614 arg_id_.Dealloc(instruction->ArgumentCount()); 581 arg_id_.Dealloc(instruction->ArgumentCount());
615 582
616 current_instruction_->LinkTo(instruction); 583 current_instruction_->LinkTo(instruction);
617 set_current_instruction(instruction); 584 set_current_instruction(instruction);
618 } 585 }
619 586
620
621 void IRRegExpMacroAssembler::CloseBlockWith(Instruction* instruction) { 587 void IRRegExpMacroAssembler::CloseBlockWith(Instruction* instruction) {
622 HANDLE_DEAD_CODE_EMISSION(); 588 HANDLE_DEAD_CODE_EMISSION();
623 589
624 ASSERT(current_instruction_ != NULL); 590 ASSERT(current_instruction_ != NULL);
625 ASSERT(current_instruction_->next() == NULL); 591 ASSERT(current_instruction_->next() == NULL);
626 592
627 temp_id_.Dealloc(instruction->InputCount()); 593 temp_id_.Dealloc(instruction->InputCount());
628 arg_id_.Dealloc(instruction->ArgumentCount()); 594 arg_id_.Dealloc(instruction->ArgumentCount());
629 595
630 current_instruction_->LinkTo(instruction); 596 current_instruction_->LinkTo(instruction);
631 set_current_instruction(NULL); 597 set_current_instruction(NULL);
632 } 598 }
633 599
634
635 void IRRegExpMacroAssembler::GoTo(BlockLabel* to) { 600 void IRRegExpMacroAssembler::GoTo(BlockLabel* to) {
636 if (to == NULL) { 601 if (to == NULL) {
637 Backtrack(); 602 Backtrack();
638 } else { 603 } else {
639 to->SetLinked(); 604 to->SetLinked();
640 GoTo(to->block()); 605 GoTo(to->block());
641 } 606 }
642 } 607 }
643 608
644
645 // Closes the current block with a goto, and unsets current_instruction_. 609 // Closes the current block with a goto, and unsets current_instruction_.
646 // BindBlock() must be called before emission can continue. 610 // BindBlock() must be called before emission can continue.
647 void IRRegExpMacroAssembler::GoTo(JoinEntryInstr* to) { 611 void IRRegExpMacroAssembler::GoTo(JoinEntryInstr* to) {
648 HANDLE_DEAD_CODE_EMISSION(); 612 HANDLE_DEAD_CODE_EMISSION();
649 613
650 ASSERT(current_instruction_ != NULL); 614 ASSERT(current_instruction_ != NULL);
651 ASSERT(current_instruction_->next() == NULL); 615 ASSERT(current_instruction_->next() == NULL);
652 current_instruction_->Goto(to); 616 current_instruction_->Goto(to);
653 set_current_instruction(NULL); 617 set_current_instruction(NULL);
654 } 618 }
655 619
656
657 PushArgumentInstr* IRRegExpMacroAssembler::PushArgument(Value* value) { 620 PushArgumentInstr* IRRegExpMacroAssembler::PushArgument(Value* value) {
658 arg_id_.Alloc(); 621 arg_id_.Alloc();
659 PushArgumentInstr* push = new (Z) PushArgumentInstr(value); 622 PushArgumentInstr* push = new (Z) PushArgumentInstr(value);
660 // Do *not* use Do() for push argument instructions. 623 // Do *not* use Do() for push argument instructions.
661 AppendInstruction(push); 624 AppendInstruction(push);
662 return push; 625 return push;
663 } 626 }
664 627
665
666 PushArgumentInstr* IRRegExpMacroAssembler::PushLocal(LocalVariable* local) { 628 PushArgumentInstr* IRRegExpMacroAssembler::PushLocal(LocalVariable* local) {
667 return PushArgument(Bind(LoadLocal(local))); 629 return PushArgument(Bind(LoadLocal(local)));
668 } 630 }
669 631
670
671 void IRRegExpMacroAssembler::Print(const char* str) { 632 void IRRegExpMacroAssembler::Print(const char* str) {
672 Print(PushArgument(Bind(new (Z) ConstantInstr( 633 Print(PushArgument(Bind(new (Z) ConstantInstr(
673 String::ZoneHandle(Z, String::New(str, Heap::kOld)))))); 634 String::ZoneHandle(Z, String::New(str, Heap::kOld))))));
674 } 635 }
675 636
676
677 void IRRegExpMacroAssembler::Print(PushArgumentInstr* argument) { 637 void IRRegExpMacroAssembler::Print(PushArgumentInstr* argument) {
678 const Library& lib = Library::Handle(Library::CoreLibrary()); 638 const Library& lib = Library::Handle(Library::CoreLibrary());
679 const Function& print_fn = 639 const Function& print_fn =
680 Function::ZoneHandle(Z, lib.LookupFunctionAllowPrivate(Symbols::print())); 640 Function::ZoneHandle(Z, lib.LookupFunctionAllowPrivate(Symbols::print()));
681 Do(StaticCall(print_fn, argument)); 641 Do(StaticCall(print_fn, argument));
682 } 642 }
683 643
684
685 void IRRegExpMacroAssembler::PrintBlocks() { 644 void IRRegExpMacroAssembler::PrintBlocks() {
686 for (intptr_t i = 0; i < blocks_.length(); i++) { 645 for (intptr_t i = 0; i < blocks_.length(); i++) {
687 FlowGraphPrinter::PrintBlock(blocks_[i], false); 646 FlowGraphPrinter::PrintBlock(blocks_[i], false);
688 } 647 }
689 } 648 }
690 649
691
692 intptr_t IRRegExpMacroAssembler::stack_limit_slack() { 650 intptr_t IRRegExpMacroAssembler::stack_limit_slack() {
693 return 32; 651 return 32;
694 } 652 }
695 653
696
697 void IRRegExpMacroAssembler::AdvanceCurrentPosition(intptr_t by) { 654 void IRRegExpMacroAssembler::AdvanceCurrentPosition(intptr_t by) {
698 TAG(); 655 TAG();
699 if (by != 0) { 656 if (by != 0) {
700 PushArgumentInstr* cur_pos_push = PushLocal(current_position_); 657 PushArgumentInstr* cur_pos_push = PushLocal(current_position_);
701 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); 658 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by)));
702 659
703 Value* new_pos_value = Bind(Add(cur_pos_push, by_push)); 660 Value* new_pos_value = Bind(Add(cur_pos_push, by_push));
704 StoreLocal(current_position_, new_pos_value); 661 StoreLocal(current_position_, new_pos_value);
705 } 662 }
706 } 663 }
707 664
708
709 void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) { 665 void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) {
710 TAG(); 666 TAG();
711 ASSERT(reg >= 0); 667 ASSERT(reg >= 0);
712 ASSERT(reg < registers_count_); 668 ASSERT(reg < registers_count_);
713 669
714 if (by != 0) { 670 if (by != 0) {
715 PushArgumentInstr* registers_push = PushLocal(registers_); 671 PushArgumentInstr* registers_push = PushLocal(registers_);
716 PushArgumentInstr* index_push = PushRegisterIndex(reg); 672 PushArgumentInstr* index_push = PushRegisterIndex(reg);
717 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); 673 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
718 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); 674 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by)));
719 PushArgumentInstr* value_push = PushArgument(Bind(Add(reg_push, by_push))); 675 PushArgumentInstr* value_push = PushArgument(Bind(Add(reg_push, by_push)));
720 StoreRegister(registers_push, index_push, value_push); 676 StoreRegister(registers_push, index_push, value_push);
721 } 677 }
722 } 678 }
723 679
724
725 void IRRegExpMacroAssembler::Backtrack() { 680 void IRRegExpMacroAssembler::Backtrack() {
726 TAG(); 681 TAG();
727 GoTo(backtrack_block_); 682 GoTo(backtrack_block_);
728 } 683 }
729 684
730
731 // A BindBlock is analogous to assigning a label to a basic block. 685 // A BindBlock is analogous to assigning a label to a basic block.
732 // If the BlockLabel does not yet contain a block, it is created. 686 // If the BlockLabel does not yet contain a block, it is created.
733 // If there is a current instruction, append a goto to the bound block. 687 // If there is a current instruction, append a goto to the bound block.
734 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { 688 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) {
735 ASSERT(!label->IsBound()); 689 ASSERT(!label->IsBound());
736 ASSERT(label->block()->next() == NULL); 690 ASSERT(label->block()->next() == NULL);
737 691
738 label->SetBound(block_id_.Alloc()); 692 label->SetBound(block_id_.Alloc());
739 blocks_.Add(label->block()); 693 blocks_.Add(label->block());
740 694
741 if (current_instruction_ != NULL) { 695 if (current_instruction_ != NULL) {
742 GoTo(label); 696 GoTo(label);
743 } 697 }
744 set_current_instruction(label->block()); 698 set_current_instruction(label->block());
745 699
746 // Print the id of the current block if tracing. 700 // Print the id of the current block if tracing.
747 PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id())))); 701 PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id()))));
748 } 702 }
749 703
750
751 intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() { 704 intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() {
752 intptr_t id = local_id_.Alloc(); 705 intptr_t id = local_id_.Alloc();
753 return kFirstLocalSlotFromFp - id; 706 return kFirstLocalSlotFromFp - id;
754 } 707 }
755 708
756
757 Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) { 709 Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) {
758 PushArgumentInstr* registers_push = PushLocal(registers_); 710 PushArgumentInstr* registers_push = PushLocal(registers_);
759 PushArgumentInstr* index_push = PushRegisterIndex(index); 711 PushArgumentInstr* index_push = PushRegisterIndex(index);
760 return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 712 return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
761 registers_push, index_push)); 713 registers_push, index_push));
762 } 714 }
763 715
764 void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t value) { 716 void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t value) {
765 PushArgumentInstr* registers_push = PushLocal(registers_); 717 PushArgumentInstr* registers_push = PushLocal(registers_);
766 PushArgumentInstr* index_push = PushRegisterIndex(index); 718 PushArgumentInstr* index_push = PushRegisterIndex(index);
767 PushArgumentInstr* value_push = PushArgument(Bind(Uint64Constant(value))); 719 PushArgumentInstr* value_push = PushArgument(Bind(Uint64Constant(value)));
768 StoreRegister(registers_push, index_push, value_push); 720 StoreRegister(registers_push, index_push, value_push);
769 } 721 }
770 722
771
772 void IRRegExpMacroAssembler::StoreRegister(PushArgumentInstr* registers, 723 void IRRegExpMacroAssembler::StoreRegister(PushArgumentInstr* registers,
773 PushArgumentInstr* index, 724 PushArgumentInstr* index,
774 PushArgumentInstr* value) { 725 PushArgumentInstr* value) {
775 TAG(); 726 TAG();
776 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), 727 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
777 registers, index, value)); 728 registers, index, value));
778 } 729 }
779 730
780 PushArgumentInstr* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) { 731 PushArgumentInstr* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) {
781 if (registers_count_ <= index) { 732 if (registers_count_ <= index) {
782 registers_count_ = index + 1; 733 registers_count_ = index + 1;
783 } 734 }
784 return PushArgument(Bind(Uint64Constant(index))); 735 return PushArgument(Bind(Uint64Constant(index)));
785 } 736 }
786 737
787
788 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { 738 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) {
789 TAG(); 739 TAG();
790 Definition* cur_char_def = LoadLocal(current_character_); 740 Definition* cur_char_def = LoadLocal(current_character_);
791 Definition* char_def = Uint64Constant(c); 741 Definition* char_def = Uint64Constant(c);
792 742
793 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal); 743 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal);
794 } 744 }
795 745
796
797 void IRRegExpMacroAssembler::CheckCharacterGT(uint16_t limit, 746 void IRRegExpMacroAssembler::CheckCharacterGT(uint16_t limit,
798 BlockLabel* on_greater) { 747 BlockLabel* on_greater) {
799 TAG(); 748 TAG();
800 BranchOrBacktrack( 749 BranchOrBacktrack(
801 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(limit)), 750 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(limit)),
802 on_greater); 751 on_greater);
803 } 752 }
804 753
805
806 void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) { 754 void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) {
807 TAG(); 755 TAG();
808 756
809 BlockLabel not_at_start; 757 BlockLabel not_at_start;
810 758
811 // Did we start the match at the start of the string at all? 759 // Did we start the match at the start of the string at all?
812 BranchOrBacktrack( 760 BranchOrBacktrack(
813 Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)), 761 Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
814 &not_at_start); 762 &not_at_start);
815 763
816 // If we did, are we still at the start of the input, i.e. is 764 // If we did, are we still at the start of the input, i.e. is
817 // (offset == string_length * -1)? 765 // (offset == string_length * -1)?
818 Definition* neg_len_def = 766 Definition* neg_len_def =
819 InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE), 767 InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
820 PushLocal(string_param_length_)); 768 PushLocal(string_param_length_));
821 Definition* offset_def = LoadLocal(current_position_); 769 Definition* offset_def = LoadLocal(current_position_);
822 BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start); 770 BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start);
823 771
824 BindBlock(&not_at_start); 772 BindBlock(&not_at_start);
825 } 773 }
826 774
827
828 void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) { 775 void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) {
829 TAG(); 776 TAG();
830 777
831 // Did we start the match at the start of the string at all? 778 // Did we start the match at the start of the string at all?
832 BranchOrBacktrack( 779 BranchOrBacktrack(
833 Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)), 780 Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
834 on_not_at_start); 781 on_not_at_start);
835 782
836 // If we did, are we still at the start of the input, i.e. is 783 // If we did, are we still at the start of the input, i.e. is
837 // (offset == string_length * -1)? 784 // (offset == string_length * -1)?
838 Definition* neg_len_def = 785 Definition* neg_len_def =
839 InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE), 786 InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
840 PushLocal(string_param_length_)); 787 PushLocal(string_param_length_));
841 Definition* offset_def = LoadLocal(current_position_); 788 Definition* offset_def = LoadLocal(current_position_);
842 BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start); 789 BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start);
843 } 790 }
844 791
845
846 void IRRegExpMacroAssembler::CheckCharacterLT(uint16_t limit, 792 void IRRegExpMacroAssembler::CheckCharacterLT(uint16_t limit,
847 BlockLabel* on_less) { 793 BlockLabel* on_less) {
848 TAG(); 794 TAG();
849 BranchOrBacktrack( 795 BranchOrBacktrack(
850 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(limit)), 796 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(limit)),
851 on_less); 797 on_less);
852 } 798 }
853 799
854
855 void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) { 800 void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) {
856 TAG(); 801 TAG();
857 802
858 BlockLabel fallthrough; 803 BlockLabel fallthrough;
859 804
860 Definition* head = PeekStack(); 805 Definition* head = PeekStack();
861 Definition* cur_pos_def = LoadLocal(current_position_); 806 Definition* cur_pos_def = LoadLocal(current_position_);
862 BranchOrBacktrack(Comparison(kNE, head, cur_pos_def), &fallthrough); 807 BranchOrBacktrack(Comparison(kNE, head, cur_pos_def), &fallthrough);
863 808
864 // Pop, throwing away the value. 809 // Pop, throwing away the value.
865 Do(PopStack()); 810 Do(PopStack());
866 811
867 BranchOrBacktrack(NULL, on_equal); 812 BranchOrBacktrack(NULL, on_equal);
868 813
869 BindBlock(&fallthrough); 814 BindBlock(&fallthrough);
870 } 815 }
871 816
872
873 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( 817 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
874 intptr_t start_reg, 818 intptr_t start_reg,
875 BlockLabel* on_no_match) { 819 BlockLabel* on_no_match) {
876 TAG(); 820 TAG();
877 ASSERT(start_reg + 1 <= registers_count_); 821 ASSERT(start_reg + 1 <= registers_count_);
878 822
879 BlockLabel fallthrough; 823 BlockLabel fallthrough;
880 824
881 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); 825 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1));
882 PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg)); 826 PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg));
883 StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); 827 StoreLocal(capture_length_, Bind(Sub(end_push, start_push)));
884 828
885 // The length of a capture should not be negative. This can only happen 829 // The length of a capture should not be negative. This can only happen
886 // if the end of the capture is unrecorded, or at a point earlier than 830 // if the end of the capture is unrecorded, or at a point earlier than
887 // the start of the capture. 831 // the start of the capture.
888 // BranchOrBacktrack(less, on_no_match); 832 // BranchOrBacktrack(less, on_no_match);
889 833
890 BranchOrBacktrack( 834 BranchOrBacktrack(
891 Comparison(kLT, LoadLocal(capture_length_), Uint64Constant(0)), 835 Comparison(kLT, LoadLocal(capture_length_), Uint64Constant(0)),
892 on_no_match); 836 on_no_match);
893 837
894 // If length is zero, either the capture is empty or it is completely 838 // If length is zero, either the capture is empty or it is completely
895 // uncaptured. In either case succeed immediately. 839 // uncaptured. In either case succeed immediately.
896 BranchOrBacktrack( 840 BranchOrBacktrack(
897 Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)), 841 Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
898 &fallthrough); 842 &fallthrough);
899 843
900
901 // Check that there are sufficient characters left in the input. 844 // Check that there are sufficient characters left in the input.
902 PushArgumentInstr* pos_push = PushLocal(current_position_); 845 PushArgumentInstr* pos_push = PushLocal(current_position_);
903 PushArgumentInstr* len_push = PushLocal(capture_length_); 846 PushArgumentInstr* len_push = PushLocal(capture_length_);
904 BranchOrBacktrack( 847 BranchOrBacktrack(
905 Comparison(kGT, 848 Comparison(kGT,
906 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), 849 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
907 pos_push, len_push), 850 pos_push, len_push),
908 Uint64Constant(0)), 851 Uint64Constant(0)),
909 on_no_match); 852 on_no_match);
910 853
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 BindBlock(&success); 955 BindBlock(&success);
1013 956
1014 // Move current character position to position after match. 957 // Move current character position to position after match.
1015 PushArgumentInstr* match_end_push = PushLocal(match_end_index_); 958 PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
1016 len_push = PushLocal(string_param_length_); 959 len_push = PushLocal(string_param_length_);
1017 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); 960 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
1018 961
1019 BindBlock(&fallthrough); 962 BindBlock(&fallthrough);
1020 } 963 }
1021 964
1022
1023 void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, 965 void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg,
1024 BlockLabel* on_no_match) { 966 BlockLabel* on_no_match) {
1025 TAG(); 967 TAG();
1026 ASSERT(start_reg + 1 <= registers_count_); 968 ASSERT(start_reg + 1 <= registers_count_);
1027 969
1028 BlockLabel fallthrough; 970 BlockLabel fallthrough;
1029 BlockLabel success; 971 BlockLabel success;
1030 972
1031 // Find length of back-referenced capture. 973 // Find length of back-referenced capture.
1032 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); 974 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 BindBlock(&success); 1035 BindBlock(&success);
1094 1036
1095 // Move current character position to position after match. 1037 // Move current character position to position after match.
1096 PushArgumentInstr* match_end_push = PushLocal(match_end_index_); 1038 PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
1097 len_push = PushLocal(string_param_length_); 1039 len_push = PushLocal(string_param_length_);
1098 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); 1040 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
1099 1041
1100 BindBlock(&fallthrough); 1042 BindBlock(&fallthrough);
1101 } 1043 }
1102 1044
1103
1104 void IRRegExpMacroAssembler::CheckNotCharacter(uint32_t c, 1045 void IRRegExpMacroAssembler::CheckNotCharacter(uint32_t c,
1105 BlockLabel* on_not_equal) { 1046 BlockLabel* on_not_equal) {
1106 TAG(); 1047 TAG();
1107 BranchOrBacktrack( 1048 BranchOrBacktrack(
1108 Comparison(kNE, LoadLocal(current_character_), Uint64Constant(c)), 1049 Comparison(kNE, LoadLocal(current_character_), Uint64Constant(c)),
1109 on_not_equal); 1050 on_not_equal);
1110 } 1051 }
1111 1052
1112
1113 void IRRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c, 1053 void IRRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c,
1114 uint32_t mask, 1054 uint32_t mask,
1115 BlockLabel* on_equal) { 1055 BlockLabel* on_equal) {
1116 TAG(); 1056 TAG();
1117 1057
1118 Definition* actual_def = LoadLocal(current_character_); 1058 Definition* actual_def = LoadLocal(current_character_);
1119 Definition* expected_def = Uint64Constant(c); 1059 Definition* expected_def = Uint64Constant(c);
1120 1060
1121 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); 1061 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
1122 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); 1062 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
1123 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), 1063 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1124 actual_push, mask_push); 1064 actual_push, mask_push);
1125 1065
1126 BranchOrBacktrack(Comparison(kEQ, actual_def, expected_def), on_equal); 1066 BranchOrBacktrack(Comparison(kEQ, actual_def, expected_def), on_equal);
1127 } 1067 }
1128 1068
1129
1130 void IRRegExpMacroAssembler::CheckNotCharacterAfterAnd( 1069 void IRRegExpMacroAssembler::CheckNotCharacterAfterAnd(
1131 uint32_t c, 1070 uint32_t c,
1132 uint32_t mask, 1071 uint32_t mask,
1133 BlockLabel* on_not_equal) { 1072 BlockLabel* on_not_equal) {
1134 TAG(); 1073 TAG();
1135 1074
1136 Definition* actual_def = LoadLocal(current_character_); 1075 Definition* actual_def = LoadLocal(current_character_);
1137 Definition* expected_def = Uint64Constant(c); 1076 Definition* expected_def = Uint64Constant(c);
1138 1077
1139 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); 1078 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
1140 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); 1079 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
1141 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), 1080 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1142 actual_push, mask_push); 1081 actual_push, mask_push);
1143 1082
1144 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal); 1083 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
1145 } 1084 }
1146 1085
1147
1148 void IRRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd( 1086 void IRRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd(
1149 uint16_t c, 1087 uint16_t c,
1150 uint16_t minus, 1088 uint16_t minus,
1151 uint16_t mask, 1089 uint16_t mask,
1152 BlockLabel* on_not_equal) { 1090 BlockLabel* on_not_equal) {
1153 TAG(); 1091 TAG();
1154 ASSERT(minus < Utf16::kMaxCodeUnit); // NOLINT 1092 ASSERT(minus < Utf16::kMaxCodeUnit); // NOLINT
1155 1093
1156 Definition* actual_def = LoadLocal(current_character_); 1094 Definition* actual_def = LoadLocal(current_character_);
1157 Definition* expected_def = Uint64Constant(c); 1095 Definition* expected_def = Uint64Constant(c);
1158 1096
1159 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); 1097 PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
1160 PushArgumentInstr* minus_push = PushArgument(Bind(Uint64Constant(minus))); 1098 PushArgumentInstr* minus_push = PushArgument(Bind(Uint64Constant(minus)));
1161 1099
1162 actual_push = PushArgument(Bind(Sub(actual_push, minus_push))); 1100 actual_push = PushArgument(Bind(Sub(actual_push, minus_push)));
1163 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); 1101 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
1164 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), 1102 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1165 actual_push, mask_push); 1103 actual_push, mask_push);
1166 1104
1167 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal); 1105 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
1168 } 1106 }
1169 1107
1170
1171 void IRRegExpMacroAssembler::CheckCharacterInRange(uint16_t from, 1108 void IRRegExpMacroAssembler::CheckCharacterInRange(uint16_t from,
1172 uint16_t to, 1109 uint16_t to,
1173 BlockLabel* on_in_range) { 1110 BlockLabel* on_in_range) {
1174 TAG(); 1111 TAG();
1175 ASSERT(from <= to); 1112 ASSERT(from <= to);
1176 1113
1177 // TODO(zerny): All range comparisons could be done cheaper with unsigned 1114 // TODO(zerny): All range comparisons could be done cheaper with unsigned
1178 // compares. This pattern repeats in various places. 1115 // compares. This pattern repeats in various places.
1179 1116
1180 BlockLabel on_not_in_range; 1117 BlockLabel on_not_in_range;
1181 BranchOrBacktrack( 1118 BranchOrBacktrack(
1182 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)), 1119 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)),
1183 &on_not_in_range); 1120 &on_not_in_range);
1184 BranchOrBacktrack( 1121 BranchOrBacktrack(
1185 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)), 1122 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)),
1186 &on_not_in_range); 1123 &on_not_in_range);
1187 BranchOrBacktrack(NULL, on_in_range); 1124 BranchOrBacktrack(NULL, on_in_range);
1188 1125
1189 BindBlock(&on_not_in_range); 1126 BindBlock(&on_not_in_range);
1190 } 1127 }
1191 1128
1192
1193 void IRRegExpMacroAssembler::CheckCharacterNotInRange( 1129 void IRRegExpMacroAssembler::CheckCharacterNotInRange(
1194 uint16_t from, 1130 uint16_t from,
1195 uint16_t to, 1131 uint16_t to,
1196 BlockLabel* on_not_in_range) { 1132 BlockLabel* on_not_in_range) {
1197 TAG(); 1133 TAG();
1198 ASSERT(from <= to); 1134 ASSERT(from <= to);
1199 1135
1200 BranchOrBacktrack( 1136 BranchOrBacktrack(
1201 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)), 1137 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)),
1202 on_not_in_range); 1138 on_not_in_range);
1203 1139
1204 BranchOrBacktrack( 1140 BranchOrBacktrack(
1205 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)), 1141 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)),
1206 on_not_in_range); 1142 on_not_in_range);
1207 } 1143 }
1208 1144
1209
1210 void IRRegExpMacroAssembler::CheckBitInTable(const TypedData& table, 1145 void IRRegExpMacroAssembler::CheckBitInTable(const TypedData& table,
1211 BlockLabel* on_bit_set) { 1146 BlockLabel* on_bit_set) {
1212 TAG(); 1147 TAG();
1213 1148
1214 PushArgumentInstr* table_push = 1149 PushArgumentInstr* table_push =
1215 PushArgument(Bind(new (Z) ConstantInstr(table))); 1150 PushArgument(Bind(new (Z) ConstantInstr(table)));
1216 PushArgumentInstr* index_push = PushLocal(current_character_); 1151 PushArgumentInstr* index_push = PushLocal(current_character_);
1217 1152
1218 if (mode_ != ASCII || kTableMask != Symbols::kMaxOneCharCodeSymbol) { 1153 if (mode_ != ASCII || kTableMask != Symbols::kMaxOneCharCodeSymbol) {
1219 PushArgumentInstr* mask_push = 1154 PushArgumentInstr* mask_push =
1220 PushArgument(Bind(Uint64Constant(kTableSize - 1))); 1155 PushArgument(Bind(Uint64Constant(kTableSize - 1)));
1221 index_push = PushArgument( 1156 index_push = PushArgument(
1222 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), 1157 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1223 index_push, mask_push))); 1158 index_push, mask_push)));
1224 } 1159 }
1225 1160
1226 Definition* byte_def = InstanceCall( 1161 Definition* byte_def = InstanceCall(
1227 InstanceCallDescriptor::FromToken(Token::kINDEX), table_push, index_push); 1162 InstanceCallDescriptor::FromToken(Token::kINDEX), table_push, index_push);
1228 Definition* zero_def = Int64Constant(0); 1163 Definition* zero_def = Int64Constant(0);
1229 1164
1230 BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_bit_set); 1165 BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_bit_set);
1231 } 1166 }
1232 1167
1233
1234 bool IRRegExpMacroAssembler::CheckSpecialCharacterClass( 1168 bool IRRegExpMacroAssembler::CheckSpecialCharacterClass(
1235 uint16_t type, 1169 uint16_t type,
1236 BlockLabel* on_no_match) { 1170 BlockLabel* on_no_match) {
1237 TAG(); 1171 TAG();
1238 1172
1239 // Range checks (c in min..max) are generally implemented by an unsigned 1173 // Range checks (c in min..max) are generally implemented by an unsigned
1240 // (c - min) <= (max - min) check 1174 // (c - min) <= (max - min) check
1241 switch (type) { 1175 switch (type) {
1242 case 's': 1176 case 's':
1243 // Match space-characters 1177 // Match space-characters
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 BranchOrBacktrack(NULL, on_no_match); 1294 BranchOrBacktrack(NULL, on_no_match);
1361 BindBlock(&success); 1295 BindBlock(&success);
1362 return true; 1296 return true;
1363 } 1297 }
1364 // No custom implementation (yet): s(uint16_t), S(uint16_t). 1298 // No custom implementation (yet): s(uint16_t), S(uint16_t).
1365 default: 1299 default:
1366 return false; 1300 return false;
1367 } 1301 }
1368 } 1302 }
1369 1303
1370
1371 void IRRegExpMacroAssembler::Fail() { 1304 void IRRegExpMacroAssembler::Fail() {
1372 TAG(); 1305 TAG();
1373 ASSERT(FAILURE == 0); // Return value for failure is zero. 1306 ASSERT(FAILURE == 0); // Return value for failure is zero.
1374 if (!global()) { 1307 if (!global()) {
1375 UNREACHABLE(); // Dart regexps are always global. 1308 UNREACHABLE(); // Dart regexps are always global.
1376 } 1309 }
1377 GoTo(exit_block_); 1310 GoTo(exit_block_);
1378 } 1311 }
1379 1312
1380
1381 void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg, 1313 void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg,
1382 intptr_t comparand, 1314 intptr_t comparand,
1383 BlockLabel* if_ge) { 1315 BlockLabel* if_ge) {
1384 TAG(); 1316 TAG();
1385 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); 1317 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
1386 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); 1318 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand)));
1387 BranchOrBacktrack(Comparison(kGTE, reg_push, pos), if_ge); 1319 BranchOrBacktrack(Comparison(kGTE, reg_push, pos), if_ge);
1388 } 1320 }
1389 1321
1390
1391 void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg, 1322 void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg,
1392 intptr_t comparand, 1323 intptr_t comparand,
1393 BlockLabel* if_lt) { 1324 BlockLabel* if_lt) {
1394 TAG(); 1325 TAG();
1395 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); 1326 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
1396 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); 1327 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand)));
1397 BranchOrBacktrack(Comparison(kLT, reg_push, pos), if_lt); 1328 BranchOrBacktrack(Comparison(kLT, reg_push, pos), if_lt);
1398 } 1329 }
1399 1330
1400
1401 void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq) { 1331 void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq) {
1402 TAG(); 1332 TAG();
1403 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); 1333 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
1404 PushArgumentInstr* pos = PushArgument(Bind(LoadLocal(current_position_))); 1334 PushArgumentInstr* pos = PushArgument(Bind(LoadLocal(current_position_)));
1405 BranchOrBacktrack(Comparison(kEQ, reg_push, pos), if_eq); 1335 BranchOrBacktrack(Comparison(kEQ, reg_push, pos), if_eq);
1406 } 1336 }
1407 1337
1408
1409 RegExpMacroAssembler::IrregexpImplementation 1338 RegExpMacroAssembler::IrregexpImplementation
1410 IRRegExpMacroAssembler::Implementation() { 1339 IRRegExpMacroAssembler::Implementation() {
1411 return kIRImplementation; 1340 return kIRImplementation;
1412 } 1341 }
1413 1342
1414
1415 void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset, 1343 void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset,
1416 BlockLabel* on_end_of_input, 1344 BlockLabel* on_end_of_input,
1417 bool check_bounds, 1345 bool check_bounds,
1418 intptr_t characters) { 1346 intptr_t characters) {
1419 TAG(); 1347 TAG();
1420 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 1348 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
1421 ASSERT(cp_offset < (1 << 30)); // Be sane! (And ensure negation works) 1349 ASSERT(cp_offset < (1 << 30)); // Be sane! (And ensure negation works)
1422 if (check_bounds) { 1350 if (check_bounds) {
1423 CheckPosition(cp_offset + characters - 1, on_end_of_input); 1351 CheckPosition(cp_offset + characters - 1, on_end_of_input);
1424 } 1352 }
1425 LoadCurrentCharacterUnchecked(cp_offset, characters); 1353 LoadCurrentCharacterUnchecked(cp_offset, characters);
1426 } 1354 }
1427 1355
1428
1429 void IRRegExpMacroAssembler::PopCurrentPosition() { 1356 void IRRegExpMacroAssembler::PopCurrentPosition() {
1430 TAG(); 1357 TAG();
1431 StoreLocal(current_position_, Bind(PopStack())); 1358 StoreLocal(current_position_, Bind(PopStack()));
1432 } 1359 }
1433 1360
1434
1435 void IRRegExpMacroAssembler::PopRegister(intptr_t reg) { 1361 void IRRegExpMacroAssembler::PopRegister(intptr_t reg) {
1436 TAG(); 1362 TAG();
1437 ASSERT(reg < registers_count_); 1363 ASSERT(reg < registers_count_);
1438 PushArgumentInstr* registers_push = PushLocal(registers_); 1364 PushArgumentInstr* registers_push = PushLocal(registers_);
1439 PushArgumentInstr* index_push = PushRegisterIndex(reg); 1365 PushArgumentInstr* index_push = PushRegisterIndex(reg);
1440 PushArgumentInstr* pop_push = PushArgument(Bind(PopStack())); 1366 PushArgumentInstr* pop_push = PushArgument(Bind(PopStack()));
1441 StoreRegister(registers_push, index_push, pop_push); 1367 StoreRegister(registers_push, index_push, pop_push);
1442 } 1368 }
1443 1369
1444
1445 void IRRegExpMacroAssembler::PushStack(Definition* definition) { 1370 void IRRegExpMacroAssembler::PushStack(Definition* definition) {
1446 PushArgumentInstr* stack_push = PushLocal(stack_); 1371 PushArgumentInstr* stack_push = PushLocal(stack_);
1447 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); 1372 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
1448 StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push, 1373 StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push,
1449 PushArgument(Bind(Uint64Constant(1)))))); 1374 PushArgument(Bind(Uint64Constant(1))))));
1450 stack_pointer_push = PushLocal(stack_pointer_); 1375 stack_pointer_push = PushLocal(stack_pointer_);
1451 // TODO(zerny): bind value and push could break stack discipline. 1376 // TODO(zerny): bind value and push could break stack discipline.
1452 PushArgumentInstr* value_push = PushArgument(Bind(definition)); 1377 PushArgumentInstr* value_push = PushArgument(Bind(definition));
1453 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), 1378 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1454 stack_push, stack_pointer_push, value_push)); 1379 stack_push, stack_pointer_push, value_push));
1455 } 1380 }
1456 1381
1457
1458 Definition* IRRegExpMacroAssembler::PopStack() { 1382 Definition* IRRegExpMacroAssembler::PopStack() {
1459 PushArgumentInstr* stack_push = PushLocal(stack_); 1383 PushArgumentInstr* stack_push = PushLocal(stack_);
1460 PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_); 1384 PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_);
1461 PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_); 1385 PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_);
1462 StoreLocal(stack_pointer_, Bind(Sub(stack_pointer_push2, 1386 StoreLocal(stack_pointer_, Bind(Sub(stack_pointer_push2,
1463 PushArgument(Bind(Uint64Constant(1)))))); 1387 PushArgument(Bind(Uint64Constant(1))))));
1464 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 1388 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1465 stack_push, stack_pointer_push1); 1389 stack_push, stack_pointer_push1);
1466 } 1390 }
1467 1391
1468
1469 Definition* IRRegExpMacroAssembler::PeekStack() { 1392 Definition* IRRegExpMacroAssembler::PeekStack() {
1470 PushArgumentInstr* stack_push = PushLocal(stack_); 1393 PushArgumentInstr* stack_push = PushLocal(stack_);
1471 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); 1394 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
1472 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 1395 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1473 stack_push, stack_pointer_push); 1396 stack_push, stack_pointer_push);
1474 } 1397 }
1475 1398
1476
1477 // Pushes the location corresponding to label to the backtracking stack. 1399 // Pushes the location corresponding to label to the backtracking stack.
1478 void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) { 1400 void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) {
1479 TAG(); 1401 TAG();
1480 1402
1481 // Ensure that targets of indirect jumps are never accessed through a 1403 // Ensure that targets of indirect jumps are never accessed through a
1482 // normal control flow instructions by creating a new block for each backtrack 1404 // normal control flow instructions by creating a new block for each backtrack
1483 // target. 1405 // target.
1484 IndirectEntryInstr* indirect_target = IndirectWithJoinGoto(label->block()); 1406 IndirectEntryInstr* indirect_target = IndirectWithJoinGoto(label->block());
1485 1407
1486 // Add a fake edge from the graph entry for data flow analysis. 1408 // Add a fake edge from the graph entry for data flow analysis.
1487 entry_block_->AddIndirectEntry(indirect_target); 1409 entry_block_->AddIndirectEntry(indirect_target);
1488 1410
1489 ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id()); 1411 ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id());
1490 PushStack(offset); 1412 PushStack(offset);
1491 CheckStackLimit(); 1413 CheckStackLimit();
1492 } 1414 }
1493 1415
1494
1495 void IRRegExpMacroAssembler::PushCurrentPosition() { 1416 void IRRegExpMacroAssembler::PushCurrentPosition() {
1496 TAG(); 1417 TAG();
1497 PushStack(LoadLocal(current_position_)); 1418 PushStack(LoadLocal(current_position_));
1498 } 1419 }
1499 1420
1500
1501 void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { 1421 void IRRegExpMacroAssembler::PushRegister(intptr_t reg) {
1502 TAG(); 1422 TAG();
1503 // TODO(zerny): Refactor PushStack so it can be reused here. 1423 // TODO(zerny): Refactor PushStack so it can be reused here.
1504 PushArgumentInstr* stack_push = PushLocal(stack_); 1424 PushArgumentInstr* stack_push = PushLocal(stack_);
1505 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); 1425 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
1506 StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push, 1426 StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push,
1507 PushArgument(Bind(Uint64Constant(1)))))); 1427 PushArgument(Bind(Uint64Constant(1))))));
1508 stack_pointer_push = PushLocal(stack_pointer_); 1428 stack_pointer_push = PushLocal(stack_pointer_);
1509 // TODO(zerny): bind value and push could break stack discipline. 1429 // TODO(zerny): bind value and push could break stack discipline.
1510 PushArgumentInstr* value_push = PushArgument(LoadRegister(reg)); 1430 PushArgumentInstr* value_push = PushArgument(LoadRegister(reg));
1511 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), 1431 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1512 stack_push, stack_pointer_push, value_push)); 1432 stack_push, stack_pointer_push, value_push));
1513 CheckStackLimit(); 1433 CheckStackLimit();
1514 } 1434 }
1515 1435
1516
1517 // Checks that (stack.capacity - stack_limit_slack) > stack_pointer. 1436 // Checks that (stack.capacity - stack_limit_slack) > stack_pointer.
1518 // This ensures that up to stack_limit_slack stack pushes can be 1437 // This ensures that up to stack_limit_slack stack pushes can be
1519 // done without exhausting the stack space. If the check fails the 1438 // done without exhausting the stack space. If the check fails the
1520 // stack will be grown. 1439 // stack will be grown.
1521 void IRRegExpMacroAssembler::CheckStackLimit() { 1440 void IRRegExpMacroAssembler::CheckStackLimit() {
1522 TAG(); 1441 TAG();
1523 PushArgumentInstr* stack_push = PushLocal(stack_); 1442 PushArgumentInstr* stack_push = PushLocal(stack_);
1524 PushArgumentInstr* length_push = PushArgument( 1443 PushArgumentInstr* length_push = PushArgument(
1525 Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle( 1444 Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle(
1526 Field::GetterSymbol(Symbols::Length()))), 1445 Field::GetterSymbol(Symbols::Length()))),
1527 stack_push))); 1446 stack_push)));
1528 PushArgumentInstr* capacity_push = PushArgument(Bind(Sub( 1447 PushArgumentInstr* capacity_push = PushArgument(Bind(Sub(
1529 length_push, PushArgument(Bind(Uint64Constant(stack_limit_slack())))))); 1448 length_push, PushArgument(Bind(Uint64Constant(stack_limit_slack()))))));
1530 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); 1449 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
1531 BranchInstr* branch = new (Z) BranchInstr( 1450 BranchInstr* branch = new (Z) BranchInstr(
1532 Comparison(kGT, capacity_push, stack_pointer_push), GetNextDeoptId()); 1451 Comparison(kGT, capacity_push, stack_pointer_push), GetNextDeoptId());
1533 CloseBlockWith(branch); 1452 CloseBlockWith(branch);
1534 1453
1535 BlockLabel grow_stack; 1454 BlockLabel grow_stack;
1536 BlockLabel fallthrough; 1455 BlockLabel fallthrough;
1537 *branch->true_successor_address() = TargetWithJoinGoto(fallthrough.block()); 1456 *branch->true_successor_address() = TargetWithJoinGoto(fallthrough.block());
1538 *branch->false_successor_address() = TargetWithJoinGoto(grow_stack.block()); 1457 *branch->false_successor_address() = TargetWithJoinGoto(grow_stack.block());
1539 1458
1540 BindBlock(&grow_stack); 1459 BindBlock(&grow_stack);
1541 GrowStack(); 1460 GrowStack();
1542 1461
1543 BindBlock(&fallthrough); 1462 BindBlock(&fallthrough);
1544 } 1463 }
1545 1464
1546
1547 void IRRegExpMacroAssembler::GrowStack() { 1465 void IRRegExpMacroAssembler::GrowStack() {
1548 TAG(); 1466 TAG();
1549 const Library& lib = Library::Handle(Library::InternalLibrary()); 1467 const Library& lib = Library::Handle(Library::InternalLibrary());
1550 const Function& grow_function = Function::ZoneHandle( 1468 const Function& grow_function = Function::ZoneHandle(
1551 Z, lib.LookupFunctionAllowPrivate(Symbols::GrowRegExpStack())); 1469 Z, lib.LookupFunctionAllowPrivate(Symbols::GrowRegExpStack()));
1552 StoreLocal(stack_, Bind(StaticCall(grow_function, PushLocal(stack_)))); 1470 StoreLocal(stack_, Bind(StaticCall(grow_function, PushLocal(stack_))));
1553 1471
1554 // Note: :stack and stack_array_cell content might diverge because each 1472 // Note: :stack and stack_array_cell content might diverge because each
1555 // instance of :matcher code has its own stack_array_cell embedded into it 1473 // instance of :matcher code has its own stack_array_cell embedded into it
1556 // as a constant but :stack is a local variable and its value might be 1474 // as a constant but :stack is a local variable and its value might be
1557 // comming from OSR or deoptimization. This means we should never use 1475 // comming from OSR or deoptimization. This means we should never use
1558 // stack_array_cell in the body of the :matcher to reload the :stack. 1476 // stack_array_cell in the body of the :matcher to reload the :stack.
1559 PushArgumentInstr* stack_cell_push = 1477 PushArgumentInstr* stack_cell_push =
1560 PushArgument(Bind(new (Z) ConstantInstr(stack_array_cell_))); 1478 PushArgument(Bind(new (Z) ConstantInstr(stack_array_cell_)));
1561 PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(0))); 1479 PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(0)));
1562 PushArgumentInstr* stack_push = PushLocal(stack_); 1480 PushArgumentInstr* stack_push = PushLocal(stack_);
1563 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), 1481 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1564 stack_cell_push, index_push, stack_push)); 1482 stack_cell_push, index_push, stack_push));
1565 } 1483 }
1566 1484
1567
1568 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { 1485 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) {
1569 TAG(); 1486 TAG();
1570 StoreLocal(current_position_, LoadRegister(reg)); 1487 StoreLocal(current_position_, LoadRegister(reg));
1571 } 1488 }
1572 1489
1573 // Resets the tip of the stack to the value stored in reg. 1490 // Resets the tip of the stack to the value stored in reg.
1574 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { 1491 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) {
1575 TAG(); 1492 TAG();
1576 ASSERT(reg < registers_count_); 1493 ASSERT(reg < registers_count_);
1577 StoreLocal(stack_pointer_, LoadRegister(reg)); 1494 StoreLocal(stack_pointer_, LoadRegister(reg));
(...skipping 13 matching lines...) Expand all
1591 StoreLocal(current_position_, Bind(Int64Constant(-by))); 1508 StoreLocal(current_position_, Bind(Int64Constant(-by)));
1592 1509
1593 // On RegExp code entry (where this operation is used), the character before 1510 // On RegExp code entry (where this operation is used), the character before
1594 // the current position is expected to be already loaded. 1511 // the current position is expected to be already loaded.
1595 // We have advanced the position, so it's safe to read backwards. 1512 // We have advanced the position, so it's safe to read backwards.
1596 LoadCurrentCharacterUnchecked(-1, 1); 1513 LoadCurrentCharacterUnchecked(-1, 1);
1597 1514
1598 BindBlock(&after_position); 1515 BindBlock(&after_position);
1599 } 1516 }
1600 1517
1601
1602 void IRRegExpMacroAssembler::SetRegister(intptr_t reg, intptr_t to) { 1518 void IRRegExpMacroAssembler::SetRegister(intptr_t reg, intptr_t to) {
1603 TAG(); 1519 TAG();
1604 // Reserved for positions! 1520 // Reserved for positions!
1605 ASSERT(reg >= saved_registers_count_); 1521 ASSERT(reg >= saved_registers_count_);
1606 StoreRegister(reg, to); 1522 StoreRegister(reg, to);
1607 } 1523 }
1608 1524
1609
1610 bool IRRegExpMacroAssembler::Succeed() { 1525 bool IRRegExpMacroAssembler::Succeed() {
1611 TAG(); 1526 TAG();
1612 GoTo(success_block_); 1527 GoTo(success_block_);
1613 return global(); 1528 return global();
1614 } 1529 }
1615 1530
1616
1617 void IRRegExpMacroAssembler::WriteCurrentPositionToRegister( 1531 void IRRegExpMacroAssembler::WriteCurrentPositionToRegister(
1618 intptr_t reg, 1532 intptr_t reg,
1619 intptr_t cp_offset) { 1533 intptr_t cp_offset) {
1620 TAG(); 1534 TAG();
1621 1535
1622 PushArgumentInstr* registers_push = PushLocal(registers_); 1536 PushArgumentInstr* registers_push = PushLocal(registers_);
1623 PushArgumentInstr* index_push = PushRegisterIndex(reg); 1537 PushArgumentInstr* index_push = PushRegisterIndex(reg);
1624 PushArgumentInstr* pos_push = PushLocal(current_position_); 1538 PushArgumentInstr* pos_push = PushLocal(current_position_);
1625 PushArgumentInstr* off_push = PushArgument(Bind(Int64Constant(cp_offset))); 1539 PushArgumentInstr* off_push = PushArgument(Bind(Int64Constant(cp_offset)));
1626 PushArgumentInstr* neg_off_push = PushArgument(Bind(Add(pos_push, off_push))); 1540 PushArgumentInstr* neg_off_push = PushArgument(Bind(Add(pos_push, off_push)));
1627 // Push the negative offset; these are converted to positive string positions 1541 // Push the negative offset; these are converted to positive string positions
1628 // within the success block. 1542 // within the success block.
1629 StoreRegister(registers_push, index_push, neg_off_push); 1543 StoreRegister(registers_push, index_push, neg_off_push);
1630 } 1544 }
1631 1545
1632
1633 void IRRegExpMacroAssembler::ClearRegisters(intptr_t reg_from, 1546 void IRRegExpMacroAssembler::ClearRegisters(intptr_t reg_from,
1634 intptr_t reg_to) { 1547 intptr_t reg_to) {
1635 TAG(); 1548 TAG();
1636 1549
1637 ASSERT(reg_from <= reg_to); 1550 ASSERT(reg_from <= reg_to);
1638 1551
1639 // In order to clear registers to a final result value of -1, set them to 1552 // In order to clear registers to a final result value of -1, set them to
1640 // (-1 - string length), the offset of -1 from the end of the string. 1553 // (-1 - string length), the offset of -1 from the end of the string.
1641 1554
1642 for (intptr_t reg = reg_from; reg <= reg_to; reg++) { 1555 for (intptr_t reg = reg_from; reg <= reg_to; reg++) {
1643 PushArgumentInstr* registers_push = PushLocal(registers_); 1556 PushArgumentInstr* registers_push = PushLocal(registers_);
1644 PushArgumentInstr* index_push = PushRegisterIndex(reg); 1557 PushArgumentInstr* index_push = PushRegisterIndex(reg);
1645 PushArgumentInstr* minus_one_push = PushArgument(Bind(Int64Constant(-1))); 1558 PushArgumentInstr* minus_one_push = PushArgument(Bind(Int64Constant(-1)));
1646 PushArgumentInstr* length_push = PushLocal(string_param_length_); 1559 PushArgumentInstr* length_push = PushLocal(string_param_length_);
1647 PushArgumentInstr* value_push = 1560 PushArgumentInstr* value_push =
1648 PushArgument(Bind(Sub(minus_one_push, length_push))); 1561 PushArgument(Bind(Sub(minus_one_push, length_push)));
1649 StoreRegister(registers_push, index_push, value_push); 1562 StoreRegister(registers_push, index_push, value_push);
1650 } 1563 }
1651 } 1564 }
1652 1565
1653
1654 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { 1566 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) {
1655 TAG(); 1567 TAG();
1656 1568
1657 PushArgumentInstr* registers_push = PushLocal(registers_); 1569 PushArgumentInstr* registers_push = PushLocal(registers_);
1658 PushArgumentInstr* index_push = PushRegisterIndex(reg); 1570 PushArgumentInstr* index_push = PushRegisterIndex(reg);
1659 PushArgumentInstr* tip_push = PushLocal(stack_pointer_); 1571 PushArgumentInstr* tip_push = PushLocal(stack_pointer_);
1660 StoreRegister(registers_push, index_push, tip_push); 1572 StoreRegister(registers_push, index_push, tip_push);
1661 } 1573 }
1662 1574
1663
1664 // Private methods: 1575 // Private methods:
1665 1576
1666
1667 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, 1577 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset,
1668 BlockLabel* on_outside_input) { 1578 BlockLabel* on_outside_input) {
1669 TAG(); 1579 TAG();
1670 Definition* curpos_def = LoadLocal(current_position_); 1580 Definition* curpos_def = LoadLocal(current_position_);
1671 Definition* cp_off_def = Int64Constant(-cp_offset); 1581 Definition* cp_off_def = Int64Constant(-cp_offset);
1672 1582
1673 // If (current_position_ < -cp_offset), we are in bounds. 1583 // If (current_position_ < -cp_offset), we are in bounds.
1674 // Remember, current_position_ is a negative offset from the string end. 1584 // Remember, current_position_ is a negative offset from the string end.
1675 1585
1676 BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def), on_outside_input); 1586 BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def), on_outside_input);
1677 } 1587 }
1678 1588
1679
1680 void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison, 1589 void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison,
1681 BlockLabel* true_successor) { 1590 BlockLabel* true_successor) {
1682 if (comparison == NULL) { // No condition 1591 if (comparison == NULL) { // No condition
1683 if (true_successor == NULL) { 1592 if (true_successor == NULL) {
1684 Backtrack(); 1593 Backtrack();
1685 return; 1594 return;
1686 } 1595 }
1687 GoTo(true_successor); 1596 GoTo(true_successor);
1688 return; 1597 return;
1689 } 1598 }
(...skipping 10 matching lines...) Expand all
1700 BlockLabel fallthrough; 1609 BlockLabel fallthrough;
1701 1610
1702 BranchInstr* branch = new (Z) BranchInstr(comparison, GetNextDeoptId()); 1611 BranchInstr* branch = new (Z) BranchInstr(comparison, GetNextDeoptId());
1703 *branch->true_successor_address() = TargetWithJoinGoto(true_successor_block); 1612 *branch->true_successor_address() = TargetWithJoinGoto(true_successor_block);
1704 *branch->false_successor_address() = TargetWithJoinGoto(fallthrough.block()); 1613 *branch->false_successor_address() = TargetWithJoinGoto(fallthrough.block());
1705 1614
1706 CloseBlockWith(branch); 1615 CloseBlockWith(branch);
1707 BindBlock(&fallthrough); 1616 BindBlock(&fallthrough);
1708 } 1617 }
1709 1618
1710
1711 TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto( 1619 TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto(
1712 JoinEntryInstr* dst) { 1620 JoinEntryInstr* dst) {
1713 TargetEntryInstr* target = new (Z) 1621 TargetEntryInstr* target = new (Z)
1714 TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId()); 1622 TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
1715 blocks_.Add(target); 1623 blocks_.Add(target);
1716 1624
1717 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId())); 1625 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId()));
1718 1626
1719 return target; 1627 return target;
1720 } 1628 }
1721 1629
1722
1723 IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto( 1630 IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
1724 JoinEntryInstr* dst) { 1631 JoinEntryInstr* dst) {
1725 IndirectEntryInstr* target = 1632 IndirectEntryInstr* target =
1726 new (Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(), 1633 new (Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(),
1727 kInvalidTryIndex, GetNextDeoptId()); 1634 kInvalidTryIndex, GetNextDeoptId());
1728 blocks_.Add(target); 1635 blocks_.Add(target);
1729 1636
1730 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId())); 1637 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId()));
1731 1638
1732 return target; 1639 return target;
1733 } 1640 }
1734 1641
1735
1736 void IRRegExpMacroAssembler::CheckPreemption(bool is_backtrack) { 1642 void IRRegExpMacroAssembler::CheckPreemption(bool is_backtrack) {
1737 TAG(); 1643 TAG();
1738 1644
1739 // We don't have the loop_depth available when compiling regexps, but 1645 // We don't have the loop_depth available when compiling regexps, but
1740 // we set loop_depth to a non-zero value because this instruction does 1646 // we set loop_depth to a non-zero value because this instruction does
1741 // not act as an OSR entry outside loops. 1647 // not act as an OSR entry outside loops.
1742 AppendInstruction(new (Z) CheckStackOverflowInstr( 1648 AppendInstruction(new (Z) CheckStackOverflowInstr(
1743 TokenPosition::kNoSource, 1649 TokenPosition::kNoSource,
1744 /*loop_depth=*/1, GetNextDeoptId(), 1650 /*loop_depth=*/1, GetNextDeoptId(),
1745 is_backtrack ? CheckStackOverflowInstr::kOsrAndPreemption 1651 is_backtrack ? CheckStackOverflowInstr::kOsrAndPreemption
1746 : CheckStackOverflowInstr::kOsrOnly)); 1652 : CheckStackOverflowInstr::kOsrOnly));
1747 } 1653 }
1748 1654
1749
1750 Definition* IRRegExpMacroAssembler::Add(PushArgumentInstr* lhs, 1655 Definition* IRRegExpMacroAssembler::Add(PushArgumentInstr* lhs,
1751 PushArgumentInstr* rhs) { 1656 PushArgumentInstr* rhs) {
1752 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs); 1657 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs);
1753 } 1658 }
1754 1659
1755
1756 Definition* IRRegExpMacroAssembler::Sub(PushArgumentInstr* lhs, 1660 Definition* IRRegExpMacroAssembler::Sub(PushArgumentInstr* lhs,
1757 PushArgumentInstr* rhs) { 1661 PushArgumentInstr* rhs) {
1758 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kSUB), lhs, rhs); 1662 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kSUB), lhs, rhs);
1759 } 1663 }
1760 1664
1761
1762 void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked( 1665 void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked(
1763 intptr_t cp_offset, 1666 intptr_t cp_offset,
1764 intptr_t characters) { 1667 intptr_t characters) {
1765 TAG(); 1668 TAG();
1766 1669
1767 ASSERT(characters == 1 || CanReadUnaligned()); 1670 ASSERT(characters == 1 || CanReadUnaligned());
1768 if (mode_ == ASCII) { 1671 if (mode_ == ASCII) {
1769 ASSERT(characters == 1 || characters == 2 || characters == 4); 1672 ASSERT(characters == 1 || characters == 2 || characters == 4);
1770 } else { 1673 } else {
1771 ASSERT(mode_ == UC16); 1674 ASSERT(mode_ == UC16);
(...skipping 10 matching lines...) Expand all
1782 PushArgument(BindLoadLocal(*string_param_length_)); 1685 PushArgument(BindLoadLocal(*string_param_length_));
1783 // Index is stored in a temporary local so that we can later load it safely. 1686 // Index is stored in a temporary local so that we can later load it safely.
1784 StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg))); 1687 StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg)));
1785 1688
1786 // Load and store the code units. 1689 // Load and store the code units.
1787 Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters); 1690 Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters);
1788 StoreLocal(current_character_, code_unit_value); 1691 StoreLocal(current_character_, code_unit_value);
1789 PRINT(PushLocal(current_character_)); 1692 PRINT(PushLocal(current_character_));
1790 } 1693 }
1791 1694
1792
1793 Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) { 1695 Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) {
1794 return LoadCodeUnitsAt(index, 1); 1696 return LoadCodeUnitsAt(index, 1);
1795 } 1697 }
1796 1698
1797
1798 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index, 1699 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index,
1799 intptr_t characters) { 1700 intptr_t characters) {
1800 // Bind the pattern as the load receiver. 1701 // Bind the pattern as the load receiver.
1801 Value* pattern_val = BindLoadLocal(*string_param_); 1702 Value* pattern_val = BindLoadLocal(*string_param_);
1802 if (RawObject::IsExternalStringClassId(specialization_cid_)) { 1703 if (RawObject::IsExternalStringClassId(specialization_cid_)) {
1803 // The data of an external string is stored through two indirections. 1704 // The data of an external string is stored through two indirections.
1804 intptr_t external_offset = 0; 1705 intptr_t external_offset = 0;
1805 intptr_t data_offset = 0; 1706 intptr_t data_offset = 0;
1806 if (specialization_cid_ == kExternalOneByteStringCid) { 1707 if (specialization_cid_ == kExternalOneByteStringCid) {
1807 external_offset = ExternalOneByteString::external_data_offset(); 1708 external_offset = ExternalOneByteString::external_data_offset();
(...skipping 13 matching lines...) Expand all
1821 } 1722 }
1822 1723
1823 // Here pattern_val might be untagged so this must not trigger a GC. 1724 // Here pattern_val might be untagged so this must not trigger a GC.
1824 Value* index_val = BindLoadLocal(*index); 1725 Value* index_val = BindLoadLocal(*index);
1825 1726
1826 return Bind(new (Z) LoadCodeUnitsInstr(pattern_val, index_val, characters, 1727 return Bind(new (Z) LoadCodeUnitsInstr(pattern_val, index_val, characters,
1827 specialization_cid_, 1728 specialization_cid_,
1828 TokenPosition::kNoSource)); 1729 TokenPosition::kNoSource));
1829 } 1730 }
1830 1731
1831
1832 #undef __ 1732 #undef __
1833 1733
1834 } // namespace dart 1734 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/regexp_assembler_ir.h ('k') | runtime/vm/regexp_ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698