Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 5116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5127 __ bind(¬_a_flat_string); | 5127 __ bind(¬_a_flat_string); |
| 5128 __ and_(temp.reg(), kStringRepresentationMask); | 5128 __ and_(temp.reg(), kStringRepresentationMask); |
| 5129 __ cmp(temp.reg(), kConsStringTag); | 5129 __ cmp(temp.reg(), kConsStringTag); |
| 5130 __ j(not_equal, &slow_case); | 5130 __ j(not_equal, &slow_case); |
| 5131 | 5131 |
| 5132 // ConsString. | 5132 // ConsString. |
| 5133 // Check that the right hand side is the empty string (ie if this is really a | 5133 // Check that the right hand side is the empty string (ie if this is really a |
| 5134 // flat string in a cons string). If that is not the case we would rather go | 5134 // flat string in a cons string). If that is not the case we would rather go |
| 5135 // to the runtime system now, to flatten the string. | 5135 // to the runtime system now, to flatten the string. |
| 5136 __ mov(temp.reg(), FieldOperand(object.reg(), ConsString::kSecondOffset)); | 5136 __ mov(temp.reg(), FieldOperand(object.reg(), ConsString::kSecondOffset)); |
| 5137 __ cmp(Operand(temp.reg()), Immediate(Handle<String>(Heap::empty_string()))); | 5137 __ cmp(Operand(temp.reg()), Factory::empty_string()); |
| 5138 __ j(not_equal, &slow_case); | 5138 __ j(not_equal, &slow_case); |
| 5139 // Get the first of the two strings. | 5139 // Get the first of the two strings. |
| 5140 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset)); | 5140 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset)); |
| 5141 __ jmp(&try_again_with_new_string); | 5141 __ jmp(&try_again_with_new_string); |
| 5142 | 5142 |
| 5143 __ bind(&slow_case); | 5143 __ bind(&slow_case); |
| 5144 // Move the undefined value into the result register, which will | 5144 // Move the undefined value into the result register, which will |
| 5145 // trigger the slow case. | 5145 // trigger the slow case. |
| 5146 __ Set(temp.reg(), Immediate(Factory::undefined_value())); | 5146 __ Set(temp.reg(), Immediate(Factory::undefined_value())); |
| 5147 | 5147 |
| (...skipping 3242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8390 __ bind(&done); | 8390 __ bind(&done); |
| 8391 __ ret(3 * kPointerSize); | 8391 __ ret(3 * kPointerSize); |
| 8392 | 8392 |
| 8393 // Do the runtime call to allocate the arguments object. | 8393 // Do the runtime call to allocate the arguments object. |
| 8394 __ bind(&runtime); | 8394 __ bind(&runtime); |
| 8395 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); | 8395 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); |
| 8396 } | 8396 } |
| 8397 | 8397 |
| 8398 | 8398 |
| 8399 void RegExpExecStub::Generate(MacroAssembler* masm) { | 8399 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 8400 // Just jump directly to runtime if regexp entry in generated code is turned | 8400 // Just jump directly to runtime if native RegExp is not selected at compile |
| 8401 // off. | 8401 // time or if regexp entry in generated code is turned off runtime switch or |
| 8402 // at compilation. | |
| 8403 #ifndef V8_NATIVE_REGEXP | |
| 8404 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); | |
| 8405 #endif | |
|
Lasse Reichstein
2010/01/29 08:09:08
Perhaps use #else to make all the following code g
Søren Thygesen Gjesse
2010/01/29 13:06:53
Done.
| |
| 8402 if (!FLAG_regexp_entry_native) { | 8406 if (!FLAG_regexp_entry_native) { |
| 8403 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); | 8407 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); |
| 8404 return; | 8408 return; |
| 8405 } | 8409 } |
| 8406 | 8410 |
| 8407 // Stack frame on entry. | 8411 // Stack frame on entry. |
| 8408 // esp[0]: return address | 8412 // esp[0]: return address |
| 8409 // esp[4]: last_match_info (expected JSArray) | 8413 // esp[4]: last_match_info (expected JSArray) |
| 8410 // esp[8]: previous index | 8414 // esp[8]: previous index |
| 8411 // esp[12]: subject string | 8415 // esp[12]: subject string |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 8429 | 8433 |
| 8430 // Check that the first argument is a JSRegExp object. | 8434 // Check that the first argument is a JSRegExp object. |
| 8431 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 8435 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 8432 ASSERT_EQ(0, kSmiTag); | 8436 ASSERT_EQ(0, kSmiTag); |
| 8433 __ test(eax, Immediate(kSmiTagMask)); | 8437 __ test(eax, Immediate(kSmiTagMask)); |
| 8434 __ j(zero, &runtime); | 8438 __ j(zero, &runtime); |
| 8435 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); | 8439 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); |
| 8436 __ j(not_equal, &runtime); | 8440 __ j(not_equal, &runtime); |
| 8437 // Check that the RegExp has been compiled (data contains a fixed array). | 8441 // Check that the RegExp has been compiled (data contains a fixed array). |
| 8438 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 8442 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 8439 #ifdef DEBUG | 8443 if (FLAG_debug_code) { |
| 8440 __ test(ecx, Immediate(kSmiTagMask)); | 8444 __ test(ecx, Immediate(kSmiTagMask)); |
| 8441 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); | 8445 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); |
| 8442 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); | 8446 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); |
| 8443 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | 8447 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); |
| 8444 #endif | 8448 } |
| 8445 | 8449 |
| 8446 // ecx: RegExp data (FixedArray) | 8450 // ecx: RegExp data (FixedArray) |
| 8447 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 8451 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 8448 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); | 8452 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); |
| 8449 __ cmp(Operand(ebx), Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); | 8453 __ cmp(Operand(ebx), Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 8450 __ j(not_equal, &runtime); | 8454 __ j(not_equal, &runtime); |
| 8451 | 8455 |
| 8452 // ecx: RegExp data (FixedArray) | 8456 // ecx: RegExp data (FixedArray) |
| 8453 // Check that the number of captures fit in the static offsets vector buffer. | 8457 // Check that the number of captures fit in the static offsets vector buffer. |
| 8454 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 8458 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 8469 __ j(zero, &runtime); | 8473 __ j(zero, &runtime); |
| 8470 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); | 8474 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); |
| 8471 __ j(NegateCondition(is_string), &runtime); | 8475 __ j(NegateCondition(is_string), &runtime); |
| 8472 // Get the length of the string to ebx. | 8476 // Get the length of the string to ebx. |
| 8473 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 8477 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
| 8474 | 8478 |
| 8475 // ebx: Length of subject string | 8479 // ebx: Length of subject string |
| 8476 // ecx: RegExp data (FixedArray) | 8480 // ecx: RegExp data (FixedArray) |
| 8477 // edx: Number of capture registers | 8481 // edx: Number of capture registers |
| 8478 // Check that the third argument is a positive smi. | 8482 // Check that the third argument is a positive smi. |
| 8483 // Check that the third argument is a positive smi less than the subject | |
| 8484 // string length. A negative value will be greater (usigned comparison). | |
| 8479 __ mov(eax, Operand(esp, kPreviousIndexOffset)); | 8485 __ mov(eax, Operand(esp, kPreviousIndexOffset)); |
| 8480 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | |
| 8481 __ j(not_zero, &runtime); | |
| 8482 // Check that it is not greater than the subject string length. | |
| 8483 __ SmiUntag(eax); | 8486 __ SmiUntag(eax); |
| 8484 __ cmp(eax, Operand(ebx)); | 8487 __ cmp(eax, Operand(ebx)); |
| 8485 __ j(greater, &runtime); | 8488 __ j(greater, &runtime); |
| 8486 | 8489 |
| 8487 // ecx: RegExp data (FixedArray) | 8490 // ecx: RegExp data (FixedArray) |
| 8488 // edx: Number of capture registers | 8491 // edx: Number of capture registers |
| 8489 // Check that the fourth object is a JSArray object. | 8492 // Check that the fourth object is a JSArray object. |
| 8490 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 8493 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 8491 __ test(eax, Immediate(kSmiTagMask)); | 8494 __ test(eax, Immediate(kSmiTagMask)); |
| 8492 __ j(zero, &runtime); | 8495 __ j(zero, &runtime); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 8517 ASSERT_EQ(0, kStringTag); | 8520 ASSERT_EQ(0, kStringTag); |
| 8518 ASSERT_EQ(0, kSeqStringTag); | 8521 ASSERT_EQ(0, kSeqStringTag); |
| 8519 __ test(Operand(ebx), | 8522 __ test(Operand(ebx), |
| 8520 Immediate(kIsNotStringMask | kStringRepresentationMask)); | 8523 Immediate(kIsNotStringMask | kStringRepresentationMask)); |
| 8521 __ j(zero, &seq_string); | 8524 __ j(zero, &seq_string); |
| 8522 | 8525 |
| 8523 // Check for flat cons string. | 8526 // Check for flat cons string. |
| 8524 // A flat cons string is a cons string where the second part is the empty | 8527 // A flat cons string is a cons string where the second part is the empty |
| 8525 // string. In that case the subject string is just the first part of the cons | 8528 // string. In that case the subject string is just the first part of the cons |
| 8526 // string. Also in this case the first part of the cons string is known to be | 8529 // string. Also in this case the first part of the cons string is known to be |
| 8527 // a sequential string. | 8530 // a sequential string or an external string. |
| 8528 __ mov(edx, ebx); | 8531 __ mov(edx, ebx); |
| 8529 __ and_(edx, kStringRepresentationMask); | 8532 __ and_(edx, kStringRepresentationMask); |
| 8530 __ cmp(edx, kConsStringTag); | 8533 __ cmp(edx, kConsStringTag); |
| 8531 __ j(not_equal, &runtime); | 8534 __ j(not_equal, &runtime); |
| 8532 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); | 8535 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); |
| 8533 __ cmp(Operand(edx), Immediate(Handle<String>(Heap::empty_string()))); | 8536 __ cmp(Operand(edx), Factory::empty_string()); |
| 8534 __ j(not_equal, &runtime); | 8537 __ j(not_equal, &runtime); |
| 8535 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 8538 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
| 8536 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 8539 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 8537 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 8540 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 8541 ASSERT_EQ(0, kSequentialStringTag); | |
| 8542 __ test(ebx, Immediate(kStringRepresentationMask)); | |
| 8543 __ j(not_zero, &runtime); | |
| 8538 __ and_(ebx, kStringRepresentationEncodingMask); | 8544 __ and_(ebx, kStringRepresentationEncodingMask); |
| 8539 | 8545 |
| 8540 __ bind(&seq_string); | 8546 __ bind(&seq_string); |
| 8541 // eax: subject string (sequential either ascii to two byte) | 8547 // eax: subject string (sequential either ascii to two byte) |
| 8542 // ebx: suject string type & kStringRepresentationEncodingMask | 8548 // ebx: suject string type & kStringRepresentationEncodingMask |
| 8543 // ecx: RegExp data (FixedArray) | 8549 // ecx: RegExp data (FixedArray) |
| 8544 // Check that the irregexp code has been generated for an ascii string. If | 8550 // Check that the irregexp code has been generated for an ascii string. If |
| 8545 // it has, the field contains a code object otherwise it contains the hole. | 8551 // it has, the field contains a code object otherwise it contains the hole. |
| 8546 __ cmp(ebx, kStringTag | kSeqStringTag | kTwoByteStringTag); | 8552 __ cmp(ebx, kStringTag | kSeqStringTag | kTwoByteStringTag); |
| 8547 __ j(equal, &seq_two_byte_string); | 8553 __ j(equal, &seq_two_byte_string); |
| 8548 #ifdef DEBUG | 8554 if (FLAG_debug_code) { |
| 8549 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); | 8555 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 8550 __ Check(equal, "Expected sequential ascii string"); | 8556 __ Check(equal, "Expected sequential ascii string"); |
| 8551 #endif | 8557 } |
| 8552 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 8558 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
| 8553 __ Set(edi, Immediate(1)); // Type is ascii. | 8559 __ Set(edi, Immediate(1)); // Type is ascii. |
| 8554 __ jmp(&check_code); | 8560 __ jmp(&check_code); |
| 8555 | 8561 |
| 8556 __ bind(&seq_two_byte_string); | 8562 __ bind(&seq_two_byte_string); |
| 8557 // eax: subject string | 8563 // eax: subject string |
| 8558 // ecx: RegExp data (FixedArray) | 8564 // ecx: RegExp data (FixedArray) |
| 8559 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | 8565 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
| 8560 __ Set(edi, Immediate(0)); // Type is two byte. | 8566 __ Set(edi, Immediate(0)); // Type is two byte. |
| 8561 | 8567 |
| 8562 __ bind(&check_code); | 8568 __ bind(&check_code); |
| 8563 // Check that the irregexp code has been generated for If it has, the field | 8569 // Check that the irregexp code has been generated for the actual string |
| 8564 // contains a code object otherwise it contains the hole. | 8570 // encoding. If it has, the field contains a code object otherwise it contains |
| 8571 // the hole. | |
| 8565 __ CmpObjectType(edx, CODE_TYPE, ebx); | 8572 __ CmpObjectType(edx, CODE_TYPE, ebx); |
| 8566 __ j(not_equal, &runtime); | 8573 __ j(not_equal, &runtime); |
| 8567 | 8574 |
| 8568 // eax: subject string | 8575 // eax: subject string |
| 8569 // edx: code | 8576 // edx: code |
| 8570 // edi: encoding of subject string (1 if ascii 0 if two_byte); | 8577 // edi: encoding of subject string (1 if ascii, 0 if two_byte); |
| 8571 // Load used arguments before starting to push arguments for call to native | 8578 // Load used arguments before starting to push arguments for call to native |
| 8572 // RegExp code to avoid handling changing stack height. | 8579 // RegExp code to avoid handling changing stack height. |
| 8573 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 8580 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
| 8574 __ mov(ecx, Operand(esp, kJSRegExpOffset)); | |
| 8575 __ SmiUntag(ebx); // Previous index from smi. | 8581 __ SmiUntag(ebx); // Previous index from smi. |
| 8576 | 8582 |
| 8577 // eax: subject string | 8583 // eax: subject string |
| 8578 // ebx: previous index | 8584 // ebx: previous index |
| 8579 // edx: code | 8585 // edx: code |
| 8586 // edi: encoding of subject string (1 if ascii 0 if two_byte); | |
| 8580 // All checks done. Now push arguments for native regexp code. | 8587 // All checks done. Now push arguments for native regexp code. |
| 8581 __ IncrementCounter(&Counters::regexp_entry_native, 1); | 8588 __ IncrementCounter(&Counters::regexp_entry_native, 1); |
| 8582 | 8589 |
| 8583 // Argument 7: Indicate that this is a direct call from JavaScript. | 8590 // Argument 7: Indicate that this is a direct call from JavaScript. |
| 8584 __ push(Immediate(1)); | 8591 __ push(Immediate(1)); |
| 8585 | 8592 |
| 8586 // Argument 6: Start (high end) of backtracking stack memory area. | 8593 // Argument 6: Start (high end) of backtracking stack memory area. |
| 8587 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 8594 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
| 8588 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 8595 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
| 8589 __ push(ecx); | 8596 __ push(ecx); |
| 8590 | 8597 |
| 8591 // Argument 5: static offsets vector buffer. | 8598 // Argument 5: static offsets vector buffer. |
| 8592 __ push(Immediate(ExternalReference::address_of_static_offsets_vector())); | 8599 __ push(Immediate(ExternalReference::address_of_static_offsets_vector())); |
| 8593 | 8600 |
| 8594 // Argument 4: End of string data | 8601 // Argument 4: End of string data |
| 8595 // Argument 3: Start of string data | 8602 // Argument 3: Start of string data |
| 8596 Label push_two_byte, push_rest; | 8603 Label push_two_byte, push_rest; |
| 8597 __ test(edi, Operand(edi)); | 8604 __ test(edi, Operand(edi)); |
| 8598 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); | 8605 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); |
| 8599 __ j(zero, &push_two_byte); | 8606 __ j(zero, &push_two_byte); |
| 8600 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); | 8607 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); |
| 8601 __ push(ecx); // Argument 4. | 8608 __ push(ecx); // Argument 4. |
| 8602 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); | 8609 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); |
| 8603 __ push(ecx); // Argument 3. | 8610 __ push(ecx); // Argument 3. |
| 8604 __ jmp(&push_rest); | 8611 __ jmp(&push_rest); |
| 8605 | 8612 |
| 8606 __ bind(&push_two_byte); | 8613 __ bind(&push_two_byte); |
| 8607 ASSERT(kShortSize == 2); | |
| 8608 __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize)); | 8614 __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize)); |
| 8609 __ push(ecx); // Argument 4. | 8615 __ push(ecx); // Argument 4. |
| 8610 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); | 8616 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); |
| 8611 __ push(ecx); // Argument 3. | 8617 __ push(ecx); // Argument 3. |
| 8612 | 8618 |
| 8613 __ bind(&push_rest); | 8619 __ bind(&push_rest); |
| 8614 | 8620 |
| 8615 // Argument 2: Previous index. | 8621 // Argument 2: Previous index. |
| 8616 __ push(ebx); | 8622 __ push(ebx); |
| 8617 | 8623 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 8630 __ j(equal, &success, taken); | 8636 __ j(equal, &success, taken); |
| 8631 Label failure; | 8637 Label failure; |
| 8632 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); | 8638 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); |
| 8633 __ j(equal, &failure, taken); | 8639 __ j(equal, &failure, taken); |
| 8634 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); | 8640 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); |
| 8635 // If not exception it can only be retry. Handle that in the runtime system. | 8641 // If not exception it can only be retry. Handle that in the runtime system. |
| 8636 __ j(not_equal, &runtime); | 8642 __ j(not_equal, &runtime); |
| 8637 // Result must now be exception. If there is no pending exception already a | 8643 // Result must now be exception. If there is no pending exception already a |
| 8638 // stack overflow (on the backtrack stack) was detected in RegExp code but | 8644 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 8639 // haven't created the exception yet. Handle that in the runtime system. | 8645 // haven't created the exception yet. Handle that in the runtime system. |
| 8646 // TODO(592) Rerunning the RegExp to get the stack overflow exception. | |
| 8640 ExternalReference pending_exception(Top::k_pending_exception_address); | 8647 ExternalReference pending_exception(Top::k_pending_exception_address); |
| 8641 __ mov(eax, | 8648 __ mov(eax, |
| 8642 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | 8649 Operand::StaticVariable(ExternalReference::the_hole_value_location())); |
| 8643 __ cmp(eax, Operand::StaticVariable(pending_exception)); | 8650 __ cmp(eax, Operand::StaticVariable(pending_exception)); |
| 8644 __ j(equal, &runtime); | 8651 __ j(equal, &runtime); |
| 8645 __ bind(&failure); | 8652 __ bind(&failure); |
| 8646 // For failure and exception return null. | 8653 // For failure and exception return null. |
| 8647 __ mov(Operand(eax), Factory::null_value()); | 8654 __ mov(Operand(eax), Factory::null_value()); |
| 8648 __ ret(4 * kPointerSize); | 8655 __ ret(4 * kPointerSize); |
| 8649 | 8656 |
| 8650 // Load RegExp data. | 8657 // Load RegExp data. |
| 8651 __ bind(&success); | 8658 __ bind(&success); |
| 8652 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 8659 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 8653 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 8660 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 8654 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 8661 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 8655 // Calculate number of capture registers (number_of_captures + 1) * 2. | 8662 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 8663 ASSERT_EQ(0, kSmiTag); | |
| 8664 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | |
| 8656 __ add(Operand(edx), Immediate(2)); // edx was a smi. | 8665 __ add(Operand(edx), Immediate(2)); // edx was a smi. |
| 8657 | 8666 |
| 8658 // edx: Number of capture registers | 8667 // edx: Number of capture registers |
| 8659 // Load last_match_info which is still known to be a fast case JSArray. | 8668 // Load last_match_info which is still known to be a fast case JSArray. |
| 8660 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 8669 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 8661 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); | 8670 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); |
| 8662 | 8671 |
| 8663 // ebx: last_match_info backing store (FixedArray) | 8672 // ebx: last_match_info backing store (FixedArray) |
| 8664 // edx: number of capture registers | 8673 // edx: number of capture registers |
| 8665 // Store the capture count. | 8674 // Store the capture count. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 8685 // ecx: offsets vector | 8694 // ecx: offsets vector |
| 8686 // edx: number of capture registers | 8695 // edx: number of capture registers |
| 8687 Label next_capture, done; | 8696 Label next_capture, done; |
| 8688 __ mov(eax, Operand(esp, kPreviousIndexOffset)); | 8697 __ mov(eax, Operand(esp, kPreviousIndexOffset)); |
| 8689 // Capture register counter starts from number of capture registers and | 8698 // Capture register counter starts from number of capture registers and |
| 8690 // counts down until wraping after zero. | 8699 // counts down until wraping after zero. |
| 8691 __ bind(&next_capture); | 8700 __ bind(&next_capture); |
| 8692 __ sub(Operand(edx), Immediate(1)); | 8701 __ sub(Operand(edx), Immediate(1)); |
| 8693 __ j(negative, &done); | 8702 __ j(negative, &done); |
| 8694 // Read the value from the static offsets vector buffer. | 8703 // Read the value from the static offsets vector buffer. |
| 8695 __ mov(edi, Operand(ecx, edx, times_pointer_size, 0)); | 8704 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); |
| 8696 // Perform explicit shift | 8705 // Perform explicit shift |
| 8697 ASSERT_EQ(0, kSmiTag); | 8706 ASSERT_EQ(0, kSmiTag); |
| 8698 __ shl(edi, kSmiTagSize); | 8707 __ shl(edi, kSmiTagSize); |
| 8699 // Add previous index (from its stack slot) if value is not negative. | 8708 // Add previous index (from its stack slot) if value is not negative. |
| 8700 Label capture_negative; | 8709 Label capture_negative; |
| 8701 // Carry flag set by shift above. | 8710 // Carry flag set by shift above. |
| 8702 __ j(negative, &capture_negative, not_taken); | 8711 __ j(negative, &capture_negative, not_taken); |
| 8703 __ add(edi, Operand(eax)); // Add previous index (adding smi to smi). | 8712 __ add(edi, Operand(eax)); // Add previous index (adding smi to smi). |
| 8704 __ bind(&capture_negative); | 8713 __ bind(&capture_negative); |
| 8705 // Store the smi value in the last match info. | 8714 // Store the smi value in the last match info. |
| (...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10091 | 10100 |
| 10092 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10101 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 10093 // tagged as a small integer. | 10102 // tagged as a small integer. |
| 10094 __ bind(&runtime); | 10103 __ bind(&runtime); |
| 10095 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10104 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 10096 } | 10105 } |
| 10097 | 10106 |
| 10098 #undef __ | 10107 #undef __ |
| 10099 | 10108 |
| 10100 } } // namespace v8::internal | 10109 } } // namespace v8::internal |
| OLD | NEW |