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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 521028: Direct call to native RegExp code from JavaScript (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "compiler.h" 32 #include "compiler.h"
33 #include "debug.h" 33 #include "debug.h"
34 #include "ic-inl.h" 34 #include "ic-inl.h"
35 #include "jsregexp.h"
35 #include "parser.h" 36 #include "parser.h"
37 #include "regexp-macro-assembler.h"
38 #include "regexp-stack.h"
36 #include "register-allocator-inl.h" 39 #include "register-allocator-inl.h"
37 #include "runtime.h" 40 #include "runtime.h"
38 #include "scopes.h" 41 #include "scopes.h"
39 42
40 namespace v8 { 43 namespace v8 {
41 namespace internal { 44 namespace internal {
42 45
43 #define __ ACCESS_MASM(masm_) 46 #define __ ACCESS_MASM(masm_)
44 47
45 // ------------------------------------------------------------------------- 48 // -------------------------------------------------------------------------
(...skipping 5229 matching lines...) Expand 10 before | Expand all | Expand 10 after
5275 5278
5276 Load(args->at(0)); 5279 Load(args->at(0));
5277 Load(args->at(1)); 5280 Load(args->at(1));
5278 5281
5279 StringAddStub stub(NO_STRING_ADD_FLAGS); 5282 StringAddStub stub(NO_STRING_ADD_FLAGS);
5280 Result answer = frame_->CallStub(&stub, 2); 5283 Result answer = frame_->CallStub(&stub, 2);
5281 frame_->Push(&answer); 5284 frame_->Push(&answer);
5282 } 5285 }
5283 5286
5284 5287
5288 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) {
5289 ASSERT_EQ(args->length(), 4);
5290
5291 // Load the arguments on the stack and call the stub.
5292 Load(args->at(0));
5293 Load(args->at(1));
5294 Load(args->at(2));
5295 Load(args->at(3));
5296 RegExpExecStub stub;
5297 Result result = frame_->CallStub(&stub, 4);
5298 frame_->Push(&result);
5299 }
5300
5301
5285 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 5302 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
5286 if (CheckForInlineRuntimeCall(node)) { 5303 if (CheckForInlineRuntimeCall(node)) {
5287 return; 5304 return;
5288 } 5305 }
5289 5306
5290 ZoneList<Expression*>* args = node->arguments(); 5307 ZoneList<Expression*>* args = node->arguments();
5291 Comment cmnt(masm_, "[ CallRuntime"); 5308 Comment cmnt(masm_, "[ CallRuntime");
5292 Runtime::Function* function = node->function(); 5309 Runtime::Function* function = node->function();
5293 5310
5294 if (function == NULL) { 5311 if (function == NULL) {
(...skipping 2607 matching lines...) Expand 10 before | Expand all | Expand 10 after
7902 // Return and remove the on-stack parameters. 7919 // Return and remove the on-stack parameters.
7903 __ bind(&done); 7920 __ bind(&done);
7904 __ ret(3 * kPointerSize); 7921 __ ret(3 * kPointerSize);
7905 7922
7906 // Do the runtime call to allocate the arguments object. 7923 // Do the runtime call to allocate the arguments object.
7907 __ bind(&runtime); 7924 __ bind(&runtime);
7908 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); 7925 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1);
7909 } 7926 }
7910 7927
7911 7928
7929 void RegExpExecStub::Generate(MacroAssembler* masm) {
7930 // Just jump directly to runtime if regexp entry in generated code is turned
7931 // off.
7932 if (!FLAG_regexp_entry_native) {
7933 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1);
7934 return;
7935 }
7936
7937 // Stack frame on entry.
7938 // esp[0]: return address
7939 // esp[4]: last_match_info (expected JSArray)
7940 // esp[8]: previous index
7941 // esp[12]: subject string
7942 // esp[16]: JSRegExp object
7943
7944 Label runtime;
7945
7946 // Check that the first argument is a JSRegExp object.
7947 __ mov(eax, Operand(esp, 4 * kPointerSize));
7948 ASSERT_EQ(0, kSmiTag);
7949 __ test(eax, Immediate(kSmiTagMask));
7950 __ j(zero, &runtime);
7951 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
7952 __ j(not_equal, &runtime);
7953 // Check that the RegExp has been compiled (data contains a fixed array).
7954 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
7955 #ifdef DEBUG
7956 __ test(ecx, Immediate(kSmiTagMask));
7957 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected");
7958 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
7959 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
7960 #endif
7961
7962 // ecx: RegExp data (FixedArray)
7963 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
7964 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset));
7965 __ cmp(Operand(ebx), Immediate(Smi::FromInt(JSRegExp::IRREGEXP)));
7966 __ j(not_equal, &runtime);
7967
7968 // ecx: RegExp data (FixedArray)
7969 // Check that the number of captures fit in the static offsets vector buffer.
7970 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
7971 // Calculate number of capture registers (number_of_captures + 1) * 2. This
7972 // uses the asumption that smis are 2 * their untagged value.
7973 ASSERT_EQ(0, kSmiTag);
7974 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
7975 __ add(Operand(edx), Immediate(2)); // edx was a smi.
7976 // Check that the static offsets vector buffer is large enough.
7977 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize);
7978 __ j(above, &runtime);
7979
7980 // ecx: RegExp data (FixedArray)
7981 // edx: Number of capture registers
7982 // Check that the second argument is a string.
7983 __ mov(eax, Operand(esp, 3 * kPointerSize));
7984 __ test(eax, Immediate(kSmiTagMask));
7985 __ j(zero, &runtime);
7986 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
7987 __ j(NegateCondition(is_string), &runtime);
7988 // Get the length of the string to ebx.
7989 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
7990
7991 // ebx: Length of subject string
7992 // ecx: RegExp data (FixedArray)
7993 // edx: Number of capture registers
7994 // Check that the third argument is a positive smi.
7995 __ mov(eax, Operand(esp, 2 * kPointerSize));
7996 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
7997 __ j(not_zero, &runtime);
7998 // Check that it is not greater than the subject string length.
7999 __ SmiUntag(eax);
8000 __ cmp(eax, Operand(ebx));
8001 __ j(greater, &runtime);
8002
8003 // ecx: RegExp data (FixedArray)
8004 // edx: Number of capture registers
8005 // Check that the fourth object is a JSArray object.
8006 __ mov(eax, Operand(esp, 1 * kPointerSize));
8007 __ test(eax, Immediate(kSmiTagMask));
8008 __ j(zero, &runtime);
8009 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
8010 __ j(not_equal, &runtime);
8011 // Check that the JSArray is in fast case.
8012 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
8013 __ cmp(eax, Factory::fixed_array_map());
8014 __ j(not_equal, &runtime);
8015 // Check that the last match info has space for the capture registers and the
8016 // additional information.
8017 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
8018 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead));
8019 __ cmp(edx, Operand(eax));
8020 __ j(greater, &runtime);
8021
8022 // ecx: RegExp data (FixedArray)
8023 // Check the representation and encoding of the subject string (only support
8024 // flat ascii strings).
8025 __ mov(eax, Operand(esp, 3 * kPointerSize));
8026 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
8027 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
8028 __ and_(ebx, kStringRepresentationMask | kStringEncodingMask);
8029 __ cmp(ebx, kSeqStringTag | kAsciiStringTag);
8030 __ j(not_equal, &runtime);
8031
8032 // ecx: RegExp data (FixedArray)
8033 // Ensure that a RegExp stack is allocated.
8034 ExternalReference address_of_regexp_stack_memory_address =
8035 ExternalReference::address_of_regexp_stack_memory_address();
8036 ExternalReference address_of_regexp_stack_memory_size =
8037 ExternalReference::address_of_regexp_stack_memory_size();
8038 __ mov(eax, Operand::StaticVariable(address_of_regexp_stack_memory_size));
8039 __ test(eax, Operand(eax));
8040 __ j(zero, &runtime, not_taken);
8041
8042 // ecx: RegExp data (FixedArray)
8043 // Check that the irregexp code has been generated for an ascii string. If
8044 // it has the field contains a code object otherwise it contains the hole.
8045 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
8046 __ CmpObjectType(edx, CODE_TYPE, ebx);
8047 __ j(not_equal, &runtime);
8048
8049 // Load used arguments before starting to push arguments for call to native
8050 // RegExp code to avoid handling changing stack height.
8051 __ mov(eax, Operand(esp, 3 * kPointerSize)); // Subject string.
8052 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // Previous index.
8053 __ mov(ecx, Operand(esp, 4 * kPointerSize)); // JSRegExp object.
8054 __ SmiUntag(ebx); // Previous index from sim.
8055
8056 // eax: subject string
8057 // ebx: previous index
8058 // edx: code
8059 // All checks done. Now push arguments for native regexp code.
8060 __ IncrementCounter(&Counters::regexp_entry_native, 1);
8061
8062 // Argument 8: Indicate that this is a direct call from JavaScript.
8063 __ push(Immediate(1));
8064
8065 // Argument 7: Start (high end) of backtracking stack memory area.
8066 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address));
8067 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
8068 __ push(ecx);
8069
8070 // Argument 6: At start of string?
8071 __ xor_(Operand(ecx), ecx); // setcc only operated on cl (lower byte of ecx).
8072 __ test(ebx, Operand(ebx));
8073 __ setcc(zero, ecx); // 1 if 0 (start of string), 0 if positive.
8074 __ push(ecx);
8075
8076 // Argument 5: static offsets vector buffer.
8077 __ push(Immediate(ExternalReference::address_of_static_offsets_vector()));
8078
8079 // Argument 4: End of string data.
8080 __ mov(ecx, FieldOperand(eax, String::kLengthOffset));
8081 __ add(ecx, Operand(eax));
8082 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8083 __ push(ecx);
8084
8085 // Argument 3: Start of string data.
8086 __ mov(ecx, ebx);
8087 __ add(ebx, Operand(eax)); // String is ASCII.
8088 __ add(Operand(ebx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8089 __ push(ebx);
8090
8091 // Argument 2: Previous index.
8092 __ push(ecx);
8093
8094 // Argument 1: Subject string.
8095 __ push(eax);
8096
8097 // Locate the code entry and call it.
8098 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
8099 __ call(Operand(edx));
8100 // Remove arguments.
8101 __ add(Operand(esp), Immediate(8 * kPointerSize));
8102
8103 // Check the result.
8104 Label success;
8105 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS);
8106 __ j(equal, &success, taken);
8107 Label failure;
8108 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
8109 __ j(equal, &failure, taken);
8110 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
8111 // If not exception it can only be retry. Handle that in the runtime system.
8112 __ j(not_equal, &runtime);
8113 // Result must now be exception. If there is no pending exception already a
8114 // stack overflow (on the backtrack stack) was detected in RegExp code but
8115 // haven't created the exception yet. Handle that in the runtime system.
8116 ExternalReference pending_exception(Top::k_pending_exception_address);
8117 __ mov(eax,
8118 Operand::StaticVariable(ExternalReference::the_hole_value_location()));
8119 __ cmp(eax, Operand::StaticVariable(pending_exception));
8120 __ j(equal, &runtime);
8121 __ bind(&failure);
8122 // For failure and exception return null.
8123 __ mov(Operand(eax), Factory::null_value());
8124 __ ret(4 * kPointerSize);
8125
8126 // Load RegExp data.
8127 __ bind(&success);
8128 __ mov(eax, Operand(esp, 4 * kPointerSize));
8129 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
8130 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
8131 // Calculate number of capture registers (number_of_captures + 1) * 2.
8132 __ add(Operand(edx), Immediate(2)); // edx was a smi.
8133
8134 // edx: Number of capture registers
8135 // Load last_match_info which is still known to be a fast case JSArray.
8136 __ mov(eax, Operand(esp, 1 * kPointerSize));
8137 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
8138
8139 // ebx: last_match_info backing store (FixedArray)
8140 // edx: number of capture registers
8141 // Store the capture count.
8142 __ SmiTag(edx); // Number of capture registers to smi.
8143 __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx);
8144 __ SmiUntag(edx); // Number of capture registers back from smi.
8145 // Store last subject and last input.
8146 __ mov(eax, Operand(esp, 3 * kPointerSize));
8147 __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax);
8148 __ mov(ecx, ebx);
8149 __ RecordWrite(ecx, RegExpImpl::kLastSubjectOffset, eax, edi);
8150 __ mov(eax, Operand(esp, 3 * kPointerSize));
8151 __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax);
8152 __ mov(ecx, ebx);
8153 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi);
8154
8155 // Get the static offsets vector filled by the native regexp code.
8156 ExternalReference address_of_static_offsets_vector =
8157 ExternalReference::address_of_static_offsets_vector();
8158 __ mov(ecx, Immediate(address_of_static_offsets_vector));
8159
8160 // ebx: last_match_info backing store (FixedArray)
8161 // ecx: offsets vector
8162 // edx: number of capture registers
8163 Label next_capture, done;
8164 __ mov(eax, Operand(esp, 2 * kPointerSize)); // Read previous index.
8165 // Capture register counter starts from number of capture registers and
8166 // counts down until wraping after zero.
8167 __ bind(&next_capture);
8168 __ sub(Operand(edx), Immediate(1));
8169 __ j(negative, &done);
8170 // Read the value from the static offsets vector buffer.
8171 __ mov(edi, Operand(ecx, edx, times_pointer_size, 0));
8172 // Perform explicit shift
8173 ASSERT_EQ(0, kSmiTag);
8174 __ shl(edi, kSmiTagSize);
8175 // Add previous index (from its stack slot) if value is not negative.
8176 Label capture_negative;
8177 // Carry flag set by shift above.
8178 __ j(negative, &capture_negative, not_taken);
8179 __ add(edi, Operand(eax)); // Add previous index (adding smi to smi).
8180 __ bind(&capture_negative);
8181 // Store the smi value in the last match info.
8182 __ mov(FieldOperand(ebx,
8183 edx,
8184 times_pointer_size,
8185 RegExpImpl::kFirstCaptureOffset),
8186 edi);
8187 __ jmp(&next_capture);
8188 __ bind(&done);
8189
8190 // Return last match info.
8191 __ mov(eax, Operand(esp, 1 * kPointerSize));
8192 __ ret(4 * kPointerSize);
8193
8194 // Do the runtime call to execute the regexp.
8195 __ bind(&runtime);
8196 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1);
8197 }
8198
8199
7912 void CompareStub::Generate(MacroAssembler* masm) { 8200 void CompareStub::Generate(MacroAssembler* masm) {
7913 Label call_builtin, done; 8201 Label call_builtin, done;
7914 8202
7915 // NOTICE! This code is only reached after a smi-fast-case check, so 8203 // NOTICE! This code is only reached after a smi-fast-case check, so
7916 // it is certain that at least one operand isn't a smi. 8204 // it is certain that at least one operand isn't a smi.
7917 8205
7918 if (cc_ == equal) { // Both strict and non-strict. 8206 if (cc_ == equal) { // Both strict and non-strict.
7919 Label slow; // Fallthrough label. 8207 Label slow; // Fallthrough label.
7920 // Equality is almost reflexive (everything but NaN), so start by testing 8208 // Equality is almost reflexive (everything but NaN), so start by testing
7921 // for "identity and not NaN". 8209 // for "identity and not NaN".
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
8900 __ add(Operand(dest), Immediate(2)); 9188 __ add(Operand(dest), Immediate(2));
8901 } 9189 }
8902 __ sub(Operand(count), Immediate(1)); 9190 __ sub(Operand(count), Immediate(1));
8903 __ j(not_zero, &loop); 9191 __ j(not_zero, &loop);
8904 } 9192 }
8905 9193
8906 9194
8907 #undef __ 9195 #undef __
8908 9196
8909 } } // namespace v8::internal 9197 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698