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

Side by Side Diff: src/mips/code-stubs-mips.cc

Issue 13818013: Merged r13798, r13802, r13803, r13804, r13805, r14100 into 3.17 branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/3.17
Patch Set: Created 7 years, 8 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 | « no previous file | src/mips/deoptimizer-mips.cc » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 21 matching lines...) Expand all
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "codegen.h" 34 #include "codegen.h"
35 #include "regexp-macro-assembler.h" 35 #include "regexp-macro-assembler.h"
36 #include "stub-cache.h" 36 #include "stub-cache.h"
37 37
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
41 41
42 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor(
43 Isolate* isolate,
44 CodeStubInterfaceDescriptor* descriptor) {
45 static Register registers[] = { a3, a2, a1, a0 };
46 descriptor->register_param_count_ = 4;
47 descriptor->register_params_ = registers;
48 descriptor->stack_parameter_count_ = NULL;
49 descriptor->deoptimization_handler_ =
50 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
51 }
52
53
42 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( 54 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
43 Isolate* isolate, 55 Isolate* isolate,
44 CodeStubInterfaceDescriptor* descriptor) { 56 CodeStubInterfaceDescriptor* descriptor) {
45 static Register registers[] = { a1, a0 }; 57 static Register registers[] = { a1, a0 };
46 descriptor->register_param_count_ = 2; 58 descriptor->register_param_count_ = 2;
47 descriptor->register_params_ = registers; 59 descriptor->register_params_ = registers;
48 descriptor->deoptimization_handler_ = 60 descriptor->deoptimization_handler_ =
49 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); 61 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
50 } 62 }
51 63
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 &slow_case); 503 &slow_case);
492 504
493 // Return and remove the on-stack parameters. 505 // Return and remove the on-stack parameters.
494 __ DropAndRet(3); 506 __ DropAndRet(3);
495 507
496 __ bind(&slow_case); 508 __ bind(&slow_case);
497 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 509 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
498 } 510 }
499 511
500 512
501 void FastCloneShallowObjectStub::Generate(MacroAssembler* masm) {
502 // Stack layout on entry:
503 //
504 // [sp]: object literal flags.
505 // [sp + kPointerSize]: constant properties.
506 // [sp + (2 * kPointerSize)]: literal index.
507 // [sp + (3 * kPointerSize)]: literals array.
508
509 // Load boilerplate object into a3 and check if we need to create a
510 // boilerplate.
511 Label slow_case;
512 __ lw(a3, MemOperand(sp, 3 * kPointerSize));
513 __ lw(a0, MemOperand(sp, 2 * kPointerSize));
514 __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
515 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize);
516 __ Addu(a3, t0, a3);
517 __ lw(a3, MemOperand(a3));
518 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
519 __ Branch(&slow_case, eq, a3, Operand(t0));
520
521 // Check that the boilerplate contains only fast properties and we can
522 // statically determine the instance size.
523 int size = JSObject::kHeaderSize + length_ * kPointerSize;
524 __ lw(a0, FieldMemOperand(a3, HeapObject::kMapOffset));
525 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceSizeOffset));
526 __ Branch(&slow_case, ne, a0, Operand(size >> kPointerSizeLog2));
527
528 // Allocate the JS object and copy header together with all in-object
529 // properties from the boilerplate.
530 __ AllocateInNewSpace(size, v0, a1, a2, &slow_case, TAG_OBJECT);
531 for (int i = 0; i < size; i += kPointerSize) {
532 __ lw(a1, FieldMemOperand(a3, i));
533 __ sw(a1, FieldMemOperand(v0, i));
534 }
535
536 // Return and remove the on-stack parameters.
537 __ DropAndRet(4);
538
539 __ bind(&slow_case);
540 __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1);
541 }
542
543
544 // Takes a Smi and converts to an IEEE 64 bit floating point value in two 513 // Takes a Smi and converts to an IEEE 64 bit floating point value in two
545 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and 514 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and
546 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a 515 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a
547 // scratch register. Destroys the source register. No GC occurs during this 516 // scratch register. Destroys the source register. No GC occurs during this
548 // stub so you don't have to set up the frame. 517 // stub so you don't have to set up the frame.
549 class ConvertToDoubleStub : public PlatformCodeStub { 518 class ConvertToDoubleStub : public PlatformCodeStub {
550 public: 519 public:
551 ConvertToDoubleStub(Register result_reg_1, 520 ConvertToDoubleStub(Register result_reg_1,
552 Register result_reg_2, 521 Register result_reg_2,
553 Register source_reg, 522 Register source_reg,
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 1777
1809 1778
1810 static void ICCompareStub_CheckInputType(MacroAssembler* masm, 1779 static void ICCompareStub_CheckInputType(MacroAssembler* masm,
1811 Register input, 1780 Register input,
1812 Register scratch, 1781 Register scratch,
1813 CompareIC::State expected, 1782 CompareIC::State expected,
1814 Label* fail) { 1783 Label* fail) {
1815 Label ok; 1784 Label ok;
1816 if (expected == CompareIC::SMI) { 1785 if (expected == CompareIC::SMI) {
1817 __ JumpIfNotSmi(input, fail); 1786 __ JumpIfNotSmi(input, fail);
1818 } else if (expected == CompareIC::HEAP_NUMBER) { 1787 } else if (expected == CompareIC::NUMBER) {
1819 __ JumpIfSmi(input, &ok); 1788 __ JumpIfSmi(input, &ok);
1820 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 1789 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
1821 DONT_DO_SMI_CHECK); 1790 DONT_DO_SMI_CHECK);
1822 } 1791 }
1823 // We could be strict about symbol/string here, but as long as 1792 // We could be strict about symbol/string here, but as long as
1824 // hydrogen doesn't care, the stub doesn't have to care either. 1793 // hydrogen doesn't care, the stub doesn't have to care either.
1825 __ bind(&ok); 1794 __ bind(&ok);
1826 } 1795 }
1827 1796
1828 1797
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 2136
2168 // TODO(svenpanne): Use virtual functions instead of switch. 2137 // TODO(svenpanne): Use virtual functions instead of switch.
2169 void UnaryOpStub::Generate(MacroAssembler* masm) { 2138 void UnaryOpStub::Generate(MacroAssembler* masm) {
2170 switch (operand_type_) { 2139 switch (operand_type_) {
2171 case UnaryOpIC::UNINITIALIZED: 2140 case UnaryOpIC::UNINITIALIZED:
2172 GenerateTypeTransition(masm); 2141 GenerateTypeTransition(masm);
2173 break; 2142 break;
2174 case UnaryOpIC::SMI: 2143 case UnaryOpIC::SMI:
2175 GenerateSmiStub(masm); 2144 GenerateSmiStub(masm);
2176 break; 2145 break;
2177 case UnaryOpIC::HEAP_NUMBER: 2146 case UnaryOpIC::NUMBER:
2178 GenerateHeapNumberStub(masm); 2147 GenerateNumberStub(masm);
2179 break; 2148 break;
2180 case UnaryOpIC::GENERIC: 2149 case UnaryOpIC::GENERIC:
2181 GenerateGenericStub(masm); 2150 GenerateGenericStub(masm);
2182 break; 2151 break;
2183 } 2152 }
2184 } 2153 }
2185 2154
2186 2155
2187 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 2156 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
2188 // Argument is in a0 and v0 at this point, so we can overwrite a0. 2157 // Argument is in a0 and v0 at this point, so we can overwrite a0.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 __ JumpIfNotSmi(a0, non_smi); 2217 __ JumpIfNotSmi(a0, non_smi);
2249 2218
2250 // Flip bits and revert inverted smi-tag. 2219 // Flip bits and revert inverted smi-tag.
2251 __ Neg(v0, a0); 2220 __ Neg(v0, a0);
2252 __ And(v0, v0, ~kSmiTagMask); 2221 __ And(v0, v0, ~kSmiTagMask);
2253 __ Ret(); 2222 __ Ret();
2254 } 2223 }
2255 2224
2256 2225
2257 // TODO(svenpanne): Use virtual functions instead of switch. 2226 // TODO(svenpanne): Use virtual functions instead of switch.
2258 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 2227 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
2259 switch (op_) { 2228 switch (op_) {
2260 case Token::SUB: 2229 case Token::SUB:
2261 GenerateHeapNumberStubSub(masm); 2230 GenerateNumberStubSub(masm);
2262 break; 2231 break;
2263 case Token::BIT_NOT: 2232 case Token::BIT_NOT:
2264 GenerateHeapNumberStubBitNot(masm); 2233 GenerateNumberStubBitNot(masm);
2265 break; 2234 break;
2266 default: 2235 default:
2267 UNREACHABLE(); 2236 UNREACHABLE();
2268 } 2237 }
2269 } 2238 }
2270 2239
2271 2240
2272 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { 2241 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
2273 Label non_smi, slow, call_builtin; 2242 Label non_smi, slow, call_builtin;
2274 GenerateSmiCodeSub(masm, &non_smi, &call_builtin); 2243 GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
2275 __ bind(&non_smi); 2244 __ bind(&non_smi);
2276 GenerateHeapNumberCodeSub(masm, &slow); 2245 GenerateHeapNumberCodeSub(masm, &slow);
2277 __ bind(&slow); 2246 __ bind(&slow);
2278 GenerateTypeTransition(masm); 2247 GenerateTypeTransition(masm);
2279 __ bind(&call_builtin); 2248 __ bind(&call_builtin);
2280 GenerateGenericCodeFallback(masm); 2249 GenerateGenericCodeFallback(masm);
2281 } 2250 }
2282 2251
2283 2252
2284 void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) { 2253 void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) {
2285 Label non_smi, slow; 2254 Label non_smi, slow;
2286 GenerateSmiCodeBitNot(masm, &non_smi); 2255 GenerateSmiCodeBitNot(masm, &non_smi);
2287 __ bind(&non_smi); 2256 __ bind(&non_smi);
2288 GenerateHeapNumberCodeBitNot(masm, &slow); 2257 GenerateHeapNumberCodeBitNot(masm, &slow);
2289 __ bind(&slow); 2258 __ bind(&slow);
2290 GenerateTypeTransition(masm); 2259 GenerateTypeTransition(masm);
2291 } 2260 }
2292 2261
2293 2262
2294 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, 2263 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
2689 // Load the operands. 2658 // Load the operands.
2690 if (smi_operands) { 2659 if (smi_operands) {
2691 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); 2660 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2);
2692 } else { 2661 } else {
2693 // Load right operand to f14 or a2/a3. 2662 // Load right operand to f14 or a2/a3.
2694 if (right_type == BinaryOpIC::INT32) { 2663 if (right_type == BinaryOpIC::INT32) {
2695 FloatingPointHelper::LoadNumberAsInt32Double( 2664 FloatingPointHelper::LoadNumberAsInt32Double(
2696 masm, right, destination, f14, f16, a2, a3, heap_number_map, 2665 masm, right, destination, f14, f16, a2, a3, heap_number_map,
2697 scratch1, scratch2, f2, miss); 2666 scratch1, scratch2, f2, miss);
2698 } else { 2667 } else {
2699 Label* fail = (right_type == BinaryOpIC::HEAP_NUMBER) ? miss 2668 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
2700 : not_numbers;
2701 FloatingPointHelper::LoadNumber( 2669 FloatingPointHelper::LoadNumber(
2702 masm, destination, right, f14, a2, a3, heap_number_map, 2670 masm, destination, right, f14, a2, a3, heap_number_map,
2703 scratch1, scratch2, fail); 2671 scratch1, scratch2, fail);
2704 } 2672 }
2705 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it 2673 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it
2706 // jumps to |miss|. 2674 // jumps to |miss|.
2707 if (left_type == BinaryOpIC::INT32) { 2675 if (left_type == BinaryOpIC::INT32) {
2708 FloatingPointHelper::LoadNumberAsInt32Double( 2676 FloatingPointHelper::LoadNumberAsInt32Double(
2709 masm, left, destination, f12, f16, a0, a1, heap_number_map, 2677 masm, left, destination, f12, f16, a0, a1, heap_number_map,
2710 scratch1, scratch2, f2, miss); 2678 scratch1, scratch2, f2, miss);
2711 } else { 2679 } else {
2712 Label* fail = (left_type == BinaryOpIC::HEAP_NUMBER) ? miss 2680 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
2713 : not_numbers;
2714 FloatingPointHelper::LoadNumber( 2681 FloatingPointHelper::LoadNumber(
2715 masm, destination, left, f12, a0, a1, heap_number_map, 2682 masm, destination, left, f12, a0, a1, heap_number_map,
2716 scratch1, scratch2, fail); 2683 scratch1, scratch2, fail);
2717 } 2684 }
2718 } 2685 }
2719 2686
2720 // Calculate the result. 2687 // Calculate the result.
2721 if (destination == FloatingPointHelper::kFPURegisters) { 2688 if (destination == FloatingPointHelper::kFPURegisters) {
2722 // Using FPU registers: 2689 // Using FPU registers:
2723 // f12: Left value. 2690 // f12: Left value.
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
3102 // Tag the result and return. 3069 // Tag the result and return.
3103 __ SmiTag(v0, scratch1); 3070 __ SmiTag(v0, scratch1);
3104 __ Ret(); 3071 __ Ret();
3105 } else { 3072 } else {
3106 // DIV just falls through to allocating a heap number. 3073 // DIV just falls through to allocating a heap number.
3107 } 3074 }
3108 3075
3109 __ bind(&return_heap_number); 3076 __ bind(&return_heap_number);
3110 // Return a heap number, or fall through to type transition or runtime 3077 // Return a heap number, or fall through to type transition or runtime
3111 // call if we can't. 3078 // call if we can't.
3112 if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER 3079 if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::NUMBER
3113 : BinaryOpIC::INT32)) { 3080 : BinaryOpIC::INT32)) {
3114 // We are using FPU registers so s0 is available. 3081 // We are using FPU registers so s0 is available.
3115 heap_number_result = s0; 3082 heap_number_result = s0;
3116 BinaryOpStub_GenerateHeapResultAllocation(masm, 3083 BinaryOpStub_GenerateHeapResultAllocation(masm,
3117 heap_number_result, 3084 heap_number_result,
3118 heap_number_map, 3085 heap_number_map,
3119 scratch1, 3086 scratch1,
3120 scratch2, 3087 scratch2,
3121 &call_runtime, 3088 &call_runtime,
3122 mode_); 3089 mode_);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
3331 __ bind(&check); 3298 __ bind(&check);
3332 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 3299 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
3333 __ Branch(&done, ne, a0, Operand(t0)); 3300 __ Branch(&done, ne, a0, Operand(t0));
3334 if (Token::IsBitOp(op_)) { 3301 if (Token::IsBitOp(op_)) {
3335 __ li(a0, Operand(Smi::FromInt(0))); 3302 __ li(a0, Operand(Smi::FromInt(0)));
3336 } else { 3303 } else {
3337 __ LoadRoot(a0, Heap::kNanValueRootIndex); 3304 __ LoadRoot(a0, Heap::kNanValueRootIndex);
3338 } 3305 }
3339 __ bind(&done); 3306 __ bind(&done);
3340 3307
3341 GenerateHeapNumberStub(masm); 3308 GenerateNumberStub(masm);
3342 } 3309 }
3343 3310
3344 3311
3345 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 3312 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
3346 Label call_runtime, transition; 3313 Label call_runtime, transition;
3347 BinaryOpStub_GenerateFPOperation( 3314 BinaryOpStub_GenerateFPOperation(
3348 masm, left_type_, right_type_, false, 3315 masm, left_type_, right_type_, false,
3349 &transition, &call_runtime, &transition, op_, mode_); 3316 &transition, &call_runtime, &transition, op_, mode_);
3350 3317
3351 __ bind(&transition); 3318 __ bind(&transition);
3352 GenerateTypeTransition(masm); 3319 GenerateTypeTransition(masm);
3353 3320
3354 __ bind(&call_runtime); 3321 __ bind(&call_runtime);
3355 GenerateRegisterArgsPush(masm); 3322 GenerateRegisterArgsPush(masm);
(...skipping 1781 matching lines...) Expand 10 before | Expand all | Expand 10 after
5137 // sp[8]: subject string 5104 // sp[8]: subject string
5138 // sp[12]: JSRegExp object 5105 // sp[12]: JSRegExp object
5139 5106
5140 const int kLastMatchInfoOffset = 0 * kPointerSize; 5107 const int kLastMatchInfoOffset = 0 * kPointerSize;
5141 const int kPreviousIndexOffset = 1 * kPointerSize; 5108 const int kPreviousIndexOffset = 1 * kPointerSize;
5142 const int kSubjectOffset = 2 * kPointerSize; 5109 const int kSubjectOffset = 2 * kPointerSize;
5143 const int kJSRegExpOffset = 3 * kPointerSize; 5110 const int kJSRegExpOffset = 3 * kPointerSize;
5144 5111
5145 Isolate* isolate = masm->isolate(); 5112 Isolate* isolate = masm->isolate();
5146 5113
5147 Label runtime, invoke_regexp; 5114 Label runtime;
5148
5149 // Allocation of registers for this function. These are in callee save 5115 // Allocation of registers for this function. These are in callee save
5150 // registers and will be preserved by the call to the native RegExp code, as 5116 // registers and will be preserved by the call to the native RegExp code, as
5151 // this code is called using the normal C calling convention. When calling 5117 // this code is called using the normal C calling convention. When calling
5152 // directly from generated code the native RegExp code will not do a GC and 5118 // directly from generated code the native RegExp code will not do a GC and
5153 // therefore the content of these registers are safe to use after the call. 5119 // therefore the content of these registers are safe to use after the call.
5154 // MIPS - using s0..s2, since we are not using CEntry Stub. 5120 // MIPS - using s0..s2, since we are not using CEntry Stub.
5155 Register subject = s0; 5121 Register subject = s0;
5156 Register regexp_data = s1; 5122 Register regexp_data = s1;
5157 Register last_match_info_elements = s2; 5123 Register last_match_info_elements = s2;
5158 5124
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
5190 5156
5191 // regexp_data: RegExp data (FixedArray) 5157 // regexp_data: RegExp data (FixedArray)
5192 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 5158 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
5193 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 5159 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
5194 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 5160 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
5195 5161
5196 // regexp_data: RegExp data (FixedArray) 5162 // regexp_data: RegExp data (FixedArray)
5197 // Check that the number of captures fit in the static offsets vector buffer. 5163 // Check that the number of captures fit in the static offsets vector buffer.
5198 __ lw(a2, 5164 __ lw(a2,
5199 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 5165 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
5200 // Calculate number of capture registers (number_of_captures + 1) * 2. This 5166 // Check (number_of_captures + 1) * 2 <= offsets vector size
5201 // uses the asumption that smis are 2 * their untagged value. 5167 // Or number_of_captures * 2 <= offsets vector size - 2
5168 // Multiplying by 2 comes for free since a2 is smi-tagged.
5202 STATIC_ASSERT(kSmiTag == 0); 5169 STATIC_ASSERT(kSmiTag == 0);
5203 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5170 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5204 __ Addu(a2, a2, Operand(2)); // a2 was a smi. 5171 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
5205 // Check that the static offsets vector buffer is large enough.
5206 __ Branch( 5172 __ Branch(
5207 &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize)); 5173 &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
5208
5209 // a2: Number of capture registers
5210 // regexp_data: RegExp data (FixedArray)
5211 // Check that the second argument is a string.
5212 __ lw(subject, MemOperand(sp, kSubjectOffset));
5213 __ JumpIfSmi(subject, &runtime);
5214 __ GetObjectType(subject, a0, a0);
5215 __ And(a0, a0, Operand(kIsNotStringMask));
5216 STATIC_ASSERT(kStringTag == 0);
5217 __ Branch(&runtime, ne, a0, Operand(zero_reg));
5218
5219 // Get the length of the string to r3.
5220 __ lw(a3, FieldMemOperand(subject, String::kLengthOffset));
5221
5222 // a2: Number of capture registers
5223 // a3: Length of subject string as a smi
5224 // subject: Subject string
5225 // regexp_data: RegExp data (FixedArray)
5226 // Check that the third argument is a positive smi less than the subject
5227 // string length. A negative value will be greater (unsigned comparison).
5228 __ lw(a0, MemOperand(sp, kPreviousIndexOffset));
5229 __ JumpIfNotSmi(a0, &runtime);
5230 __ Branch(&runtime, ls, a3, Operand(a0));
5231
5232 // a2: Number of capture registers
5233 // subject: Subject string
5234 // regexp_data: RegExp data (FixedArray)
5235 // Check that the fourth object is a JSArray object.
5236 __ lw(a0, MemOperand(sp, kLastMatchInfoOffset));
5237 __ JumpIfSmi(a0, &runtime);
5238 __ GetObjectType(a0, a1, a1);
5239 __ Branch(&runtime, ne, a1, Operand(JS_ARRAY_TYPE));
5240 // Check that the JSArray is in fast case.
5241 __ lw(last_match_info_elements,
5242 FieldMemOperand(a0, JSArray::kElementsOffset));
5243 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
5244 __ Branch(&runtime, ne, a0, Operand(
5245 isolate->factory()->fixed_array_map()));
5246 // Check that the last match info has space for the capture registers and the
5247 // additional information.
5248 __ lw(a0,
5249 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
5250 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead));
5251 __ sra(at, a0, kSmiTagSize); // Untag length for comparison.
5252 __ Branch(&runtime, gt, a2, Operand(at));
5253 5174
5254 // Reset offset for possibly sliced string. 5175 // Reset offset for possibly sliced string.
5255 __ mov(t0, zero_reg); 5176 __ mov(t0, zero_reg);
5256 // subject: Subject string 5177 __ lw(subject, MemOperand(sp, kSubjectOffset));
5257 // regexp_data: RegExp data (FixedArray) 5178 __ JumpIfSmi(subject, &runtime);
5258 // Check the representation and encoding of the subject string. 5179 __ mov(a3, subject); // Make a copy of the original subject string.
5259 Label seq_string;
5260 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5180 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5261 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 5181 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5262 // First check for flat string. None of the following string type tests will 5182 // subject: subject string
5263 // succeed if subject is not a string or a short external string. 5183 // a3: subject string
5184 // a0: subject string instance type
5185 // regexp_data: RegExp data (FixedArray)
5186 // Handle subject string according to its encoding and representation:
5187 // (1) Sequential string? If yes, go to (5).
5188 // (2) Anything but sequential or cons? If yes, go to (6).
5189 // (3) Cons string. If the string is flat, replace subject with first string.
5190 // Otherwise bailout.
5191 // (4) Is subject external? If yes, go to (7).
5192 // (5) Sequential string. Load regexp code according to encoding.
5193 // (E) Carry on.
5194 /// [...]
5195
5196 // Deferred code at the end of the stub:
5197 // (6) Not a long external string? If yes, go to (8).
5198 // (7) External string. Make it, offset-wise, look like a sequential string.
5199 // Go to (5).
5200 // (8) Short external string or not a string? If yes, bail out to runtime.
5201 // (9) Sliced string. Replace subject with parent. Go to (4).
5202
5203 Label seq_string /* 5 */, external_string /* 7 */,
5204 check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
5205 not_long_external /* 8 */;
5206
5207 // (1) Sequential string? If yes, go to (5).
5264 __ And(a1, 5208 __ And(a1,
5265 a0, 5209 a0,
5266 Operand(kIsNotStringMask | 5210 Operand(kIsNotStringMask |
5267 kStringRepresentationMask | 5211 kStringRepresentationMask |
5268 kShortExternalStringMask)); 5212 kShortExternalStringMask));
5269 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 5213 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
5270 __ Branch(&seq_string, eq, a1, Operand(zero_reg)); 5214 __ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
5271 5215
5272 // subject: Subject string 5216 // (2) Anything but sequential or cons? If yes, go to (6).
5273 // a0: instance type if Subject string
5274 // regexp_data: RegExp data (FixedArray)
5275 // a1: whether subject is a string and if yes, its string representation
5276 // Check for flat cons string or sliced string.
5277 // A flat cons string is a cons string where the second part is the empty
5278 // string. In that case the subject string is just the first part of the cons
5279 // string. Also in this case the first part of the cons string is known to be
5280 // a sequential string or an external string.
5281 // In the case of a sliced string its offset has to be taken into account.
5282 Label cons_string, external_string, check_encoding;
5283 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 5217 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5284 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 5218 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5285 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 5219 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
5286 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 5220 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
5287 __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag)); 5221 // Go to (6).
5288 __ Branch(&external_string, eq, a1, Operand(kExternalStringTag)); 5222 __ Branch(&not_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
5289 5223
5290 // Catch non-string subject or short external string. 5224 // (3) Cons string. Check that it's flat.
5291 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 5225 // Replace subject with first string and reload instance type.
5292 __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
5293 __ Branch(&runtime, ne, at, Operand(zero_reg));
5294
5295 // String is sliced.
5296 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
5297 __ sra(t0, t0, kSmiTagSize);
5298 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
5299 // t5: offset of sliced string, smi-tagged.
5300 __ jmp(&check_encoding);
5301 // String is a cons string, check whether it is flat.
5302 __ bind(&cons_string);
5303 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); 5226 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
5304 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); 5227 __ LoadRoot(a1, Heap::kEmptyStringRootIndex);
5305 __ Branch(&runtime, ne, a0, Operand(a1)); 5228 __ Branch(&runtime, ne, a0, Operand(a1));
5306 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 5229 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
5307 // Is first part of cons or parent of slice a flat string? 5230
5308 __ bind(&check_encoding); 5231 // (4) Is subject external? If yes, go to (7).
5232 __ bind(&check_underlying);
5309 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5233 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5310 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 5234 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5311 STATIC_ASSERT(kSeqStringTag == 0); 5235 STATIC_ASSERT(kSeqStringTag == 0);
5312 __ And(at, a0, Operand(kStringRepresentationMask)); 5236 __ And(at, a0, Operand(kStringRepresentationMask));
5313 __ Branch(&external_string, ne, at, Operand(zero_reg)); 5237 // The underlying external string is never a short external string.
5238 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
5239 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
5240 __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
5314 5241
5242 // (5) Sequential string. Load regexp code according to encoding.
5315 __ bind(&seq_string); 5243 __ bind(&seq_string);
5316 // subject: Subject string 5244 // subject: sequential subject string (or look-alike, external string)
5317 // regexp_data: RegExp data (FixedArray) 5245 // a3: original subject string
5318 // a0: Instance type of subject string 5246 // Load previous index and check range before a3 is overwritten. We have to
5247 // use a3 instead of subject here because subject might have been only made
5248 // to look like a sequential string when it actually is an external string.
5249 __ lw(a1, MemOperand(sp, kPreviousIndexOffset));
5250 __ JumpIfNotSmi(a1, &runtime);
5251 __ lw(a3, FieldMemOperand(a3, String::kLengthOffset));
5252 __ Branch(&runtime, ls, a3, Operand(a1));
5253 __ sra(a1, a1, kSmiTagSize); // Untag the Smi.
5254
5319 STATIC_ASSERT(kStringEncodingMask == 4); 5255 STATIC_ASSERT(kStringEncodingMask == 4);
5320 STATIC_ASSERT(kOneByteStringTag == 4); 5256 STATIC_ASSERT(kOneByteStringTag == 4);
5321 STATIC_ASSERT(kTwoByteStringTag == 0); 5257 STATIC_ASSERT(kTwoByteStringTag == 0);
5322 // Find the code object based on the assumptions above.
5323 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. 5258 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII.
5324 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); 5259 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
5325 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). 5260 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below).
5326 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 5261 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
5327 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. 5262 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
5328 5263
5264 // (E) Carry on. String handling is done.
5265 // t9: irregexp code
5329 // Check that the irregexp code has been generated for the actual string 5266 // Check that the irregexp code has been generated for the actual string
5330 // encoding. If it has, the field contains a code object otherwise it contains 5267 // encoding. If it has, the field contains a code object otherwise it contains
5331 // a smi (code flushing support). 5268 // a smi (code flushing support).
5332 __ JumpIfSmi(t9, &runtime); 5269 __ JumpIfSmi(t9, &runtime);
5333 5270
5334 // a3: encoding of subject string (1 if ASCII, 0 if two_byte);
5335 // t9: code
5336 // subject: Subject string
5337 // regexp_data: RegExp data (FixedArray)
5338 // Load used arguments before starting to push arguments for call to native
5339 // RegExp code to avoid handling changing stack height.
5340 __ lw(a1, MemOperand(sp, kPreviousIndexOffset));
5341 __ sra(a1, a1, kSmiTagSize); // Untag the Smi.
5342
5343 // a1: previous index 5271 // a1: previous index
5344 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); 5272 // a3: encoding of subject string (1 if ASCII, 0 if two_byte);
5345 // t9: code 5273 // t9: code
5346 // subject: Subject string 5274 // subject: Subject string
5347 // regexp_data: RegExp data (FixedArray) 5275 // regexp_data: RegExp data (FixedArray)
5348 // All checks done. Now push arguments for native regexp code. 5276 // All checks done. Now push arguments for native regexp code.
5349 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 5277 __ IncrementCounter(isolate->counters()->regexp_entry_native(),
5350 1, a0, a2); 5278 1, a0, a2);
5351 5279
5352 // Isolates: note we add an additional parameter here (isolate pointer). 5280 // Isolates: note we add an additional parameter here (isolate pointer).
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
5427 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 5355 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
5428 DirectCEntryStub stub; 5356 DirectCEntryStub stub;
5429 stub.GenerateCall(masm, t9); 5357 stub.GenerateCall(masm, t9);
5430 5358
5431 __ LeaveExitFrame(false, no_reg); 5359 __ LeaveExitFrame(false, no_reg);
5432 5360
5433 // v0: result 5361 // v0: result
5434 // subject: subject string (callee saved) 5362 // subject: subject string (callee saved)
5435 // regexp_data: RegExp data (callee saved) 5363 // regexp_data: RegExp data (callee saved)
5436 // last_match_info_elements: Last match info elements (callee saved) 5364 // last_match_info_elements: Last match info elements (callee saved)
5437
5438 // Check the result. 5365 // Check the result.
5439
5440 Label success; 5366 Label success;
5441 __ Branch(&success, eq, v0, Operand(1)); 5367 __ Branch(&success, eq, v0, Operand(1));
5442 // We expect exactly one result since we force the called regexp to behave 5368 // We expect exactly one result since we force the called regexp to behave
5443 // as non-global. 5369 // as non-global.
5444 Label failure; 5370 Label failure;
5445 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); 5371 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE));
5446 // If not exception it can only be retry. Handle that in the runtime system. 5372 // If not exception it can only be retry. Handle that in the runtime system.
5447 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 5373 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
5448 // Result must now be exception. If there is no pending exception already a 5374 // Result must now be exception. If there is no pending exception already a
5449 // stack overflow (on the backtrack stack) was detected in RegExp code but 5375 // stack overflow (on the backtrack stack) was detected in RegExp code but
(...skipping 20 matching lines...) Expand all
5470 __ bind(&failure); 5396 __ bind(&failure);
5471 // For failure and exception return null. 5397 // For failure and exception return null.
5472 __ li(v0, Operand(isolate->factory()->null_value())); 5398 __ li(v0, Operand(isolate->factory()->null_value()));
5473 __ DropAndRet(4); 5399 __ DropAndRet(4);
5474 5400
5475 // Process the result from the native regexp code. 5401 // Process the result from the native regexp code.
5476 __ bind(&success); 5402 __ bind(&success);
5477 __ lw(a1, 5403 __ lw(a1,
5478 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 5404 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
5479 // Calculate number of capture registers (number_of_captures + 1) * 2. 5405 // Calculate number of capture registers (number_of_captures + 1) * 2.
5406 // Multiplying by 2 comes for free since r1 is smi-tagged.
5480 STATIC_ASSERT(kSmiTag == 0); 5407 STATIC_ASSERT(kSmiTag == 0);
5481 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5408 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5482 __ Addu(a1, a1, Operand(2)); // a1 was a smi. 5409 __ Addu(a1, a1, Operand(2)); // a1 was a smi.
5483 5410
5411 __ lw(a0, MemOperand(sp, kLastMatchInfoOffset));
5412 __ JumpIfSmi(a0, &runtime);
5413 __ GetObjectType(a0, a2, a2);
5414 __ Branch(&runtime, ne, a2, Operand(JS_ARRAY_TYPE));
5415 // Check that the JSArray is in fast case.
5416 __ lw(last_match_info_elements,
5417 FieldMemOperand(a0, JSArray::kElementsOffset));
5418 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
5419 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
5420 __ Branch(&runtime, ne, a0, Operand(at));
5421 // Check that the last match info has space for the capture registers and the
5422 // additional information.
5423 __ lw(a0,
5424 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
5425 __ Addu(a2, a1, Operand(RegExpImpl::kLastMatchOverhead));
5426 __ sra(at, a0, kSmiTagSize);
5427 __ Branch(&runtime, gt, a2, Operand(at));
5428
5484 // a1: number of capture registers 5429 // a1: number of capture registers
5485 // subject: subject string 5430 // subject: subject string
5486 // Store the capture count. 5431 // Store the capture count.
5487 __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi. 5432 __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi.
5488 __ sw(a2, FieldMemOperand(last_match_info_elements, 5433 __ sw(a2, FieldMemOperand(last_match_info_elements,
5489 RegExpImpl::kLastCaptureCountOffset)); 5434 RegExpImpl::kLastCaptureCountOffset));
5490 // Store last subject and last input. 5435 // Store last subject and last input.
5491 __ sw(subject, 5436 __ sw(subject,
5492 FieldMemOperand(last_match_info_elements, 5437 FieldMemOperand(last_match_info_elements,
5493 RegExpImpl::kLastSubjectOffset)); 5438 RegExpImpl::kLastSubjectOffset));
5494 __ mov(a2, subject); 5439 __ mov(a2, subject);
5495 __ RecordWriteField(last_match_info_elements, 5440 __ RecordWriteField(last_match_info_elements,
5496 RegExpImpl::kLastSubjectOffset, 5441 RegExpImpl::kLastSubjectOffset,
5497 a2, 5442 subject,
5498 t3, 5443 t3,
5499 kRAHasNotBeenSaved, 5444 kRAHasNotBeenSaved,
5500 kDontSaveFPRegs); 5445 kDontSaveFPRegs);
5446 __ mov(subject, a2);
5501 __ sw(subject, 5447 __ sw(subject,
5502 FieldMemOperand(last_match_info_elements, 5448 FieldMemOperand(last_match_info_elements,
5503 RegExpImpl::kLastInputOffset)); 5449 RegExpImpl::kLastInputOffset));
5504 __ RecordWriteField(last_match_info_elements, 5450 __ RecordWriteField(last_match_info_elements,
5505 RegExpImpl::kLastInputOffset, 5451 RegExpImpl::kLastInputOffset,
5506 subject, 5452 subject,
5507 t3, 5453 t3,
5508 kRAHasNotBeenSaved, 5454 kRAHasNotBeenSaved,
5509 kDontSaveFPRegs); 5455 kDontSaveFPRegs);
5510 5456
(...skipping 21 matching lines...) Expand all
5532 __ sw(a3, MemOperand(a0, 0)); 5478 __ sw(a3, MemOperand(a0, 0));
5533 __ Branch(&next_capture, USE_DELAY_SLOT); 5479 __ Branch(&next_capture, USE_DELAY_SLOT);
5534 __ addiu(a0, a0, kPointerSize); // In branch delay slot. 5480 __ addiu(a0, a0, kPointerSize); // In branch delay slot.
5535 5481
5536 __ bind(&done); 5482 __ bind(&done);
5537 5483
5538 // Return last match info. 5484 // Return last match info.
5539 __ lw(v0, MemOperand(sp, kLastMatchInfoOffset)); 5485 __ lw(v0, MemOperand(sp, kLastMatchInfoOffset));
5540 __ DropAndRet(4); 5486 __ DropAndRet(4);
5541 5487
5542 // External string. Short external strings have already been ruled out. 5488 // Do the runtime call to execute the regexp.
5543 // a0: scratch 5489 __ bind(&runtime);
5490 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
5491
5492 // Deferred code for string handling.
5493 // (6) Not a long external string? If yes, go to (8).
5494 __ bind(&not_seq_nor_cons);
5495 // Go to (8).
5496 __ Branch(&not_long_external, gt, a1, Operand(kExternalStringTag));
5497
5498 // (7) External string. Make it, offset-wise, look like a sequential string.
5544 __ bind(&external_string); 5499 __ bind(&external_string);
5545 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5500 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5546 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 5501 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5547 if (FLAG_debug_code) { 5502 if (FLAG_debug_code) {
5548 // Assert that we do not have a cons or slice (indirect strings) here. 5503 // Assert that we do not have a cons or slice (indirect strings) here.
5549 // Sequential strings have already been ruled out. 5504 // Sequential strings have already been ruled out.
5550 __ And(at, a0, Operand(kIsIndirectStringMask)); 5505 __ And(at, a0, Operand(kIsIndirectStringMask));
5551 __ Assert(eq, 5506 __ Assert(eq,
5552 "external string expected, but not found", 5507 "external string expected, but not found",
5553 at, 5508 at,
5554 Operand(zero_reg)); 5509 Operand(zero_reg));
5555 } 5510 }
5556 __ lw(subject, 5511 __ lw(subject,
5557 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 5512 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
5558 // Move the pointer so that offset-wise, it looks like a sequential string. 5513 // Move the pointer so that offset-wise, it looks like a sequential string.
5559 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 5514 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
5560 __ Subu(subject, 5515 __ Subu(subject,
5561 subject, 5516 subject,
5562 SeqTwoByteString::kHeaderSize - kHeapObjectTag); 5517 SeqTwoByteString::kHeaderSize - kHeapObjectTag);
5563 __ jmp(&seq_string); 5518 __ jmp(&seq_string); // Go to (5).
5564 5519
5565 // Do the runtime call to execute the regexp. 5520 // (8) Short external string or not a string? If yes, bail out to runtime.
5566 __ bind(&runtime); 5521 __ bind(&not_long_external);
5567 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 5522 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
5523 __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
5524 __ Branch(&runtime, ne, at, Operand(zero_reg));
5525
5526 // (9) Sliced string. Replace subject with parent. Go to (4).
5527 // Load offset into t0 and replace subject string with parent.
5528 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
5529 __ sra(t0, t0, kSmiTagSize);
5530 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
5531 __ jmp(&check_underlying); // Go to (4).
5568 #endif // V8_INTERPRETED_REGEXP 5532 #endif // V8_INTERPRETED_REGEXP
5569 } 5533 }
5570 5534
5571 5535
5572 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 5536 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
5573 const int kMaxInlineLength = 100; 5537 const int kMaxInlineLength = 100;
5574 Label slowcase; 5538 Label slowcase;
5575 Label done; 5539 Label done;
5576 __ lw(a1, MemOperand(sp, kPointerSize * 2)); 5540 __ lw(a1, MemOperand(sp, kPointerSize * 2));
5577 STATIC_ASSERT(kSmiTag == 0); 5541 STATIC_ASSERT(kSmiTag == 0);
(...skipping 1457 matching lines...) Expand 10 before | Expand all | Expand 10 after
7035 __ SmiUntag(a0); 6999 __ SmiUntag(a0);
7036 __ Subu(v0, a1, a0); 7000 __ Subu(v0, a1, a0);
7037 } 7001 }
7038 __ Ret(); 7002 __ Ret();
7039 7003
7040 __ bind(&miss); 7004 __ bind(&miss);
7041 GenerateMiss(masm); 7005 GenerateMiss(masm);
7042 } 7006 }
7043 7007
7044 7008
7045 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 7009 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
7046 ASSERT(state_ == CompareIC::HEAP_NUMBER); 7010 ASSERT(state_ == CompareIC::NUMBER);
7047 7011
7048 Label generic_stub; 7012 Label generic_stub;
7049 Label unordered, maybe_undefined1, maybe_undefined2; 7013 Label unordered, maybe_undefined1, maybe_undefined2;
7050 Label miss; 7014 Label miss;
7051 7015
7052 if (left_ == CompareIC::SMI) { 7016 if (left_ == CompareIC::SMI) {
7053 __ JumpIfNotSmi(a1, &miss); 7017 __ JumpIfNotSmi(a1, &miss);
7054 } 7018 }
7055 if (right_ == CompareIC::SMI) { 7019 if (right_ == CompareIC::SMI) {
7056 __ JumpIfNotSmi(a0, &miss); 7020 __ JumpIfNotSmi(a0, &miss);
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
7634 struct AheadOfTimeWriteBarrierStubList { 7598 struct AheadOfTimeWriteBarrierStubList {
7635 Register object, value, address; 7599 Register object, value, address;
7636 RememberedSetAction action; 7600 RememberedSetAction action;
7637 }; 7601 };
7638 7602
7639 #define REG(Name) { kRegister_ ## Name ## _Code } 7603 #define REG(Name) { kRegister_ ## Name ## _Code }
7640 7604
7641 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { 7605 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
7642 // Used in RegExpExecStub. 7606 // Used in RegExpExecStub.
7643 { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET }, 7607 { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET },
7644 { REG(s2), REG(a2), REG(t3), EMIT_REMEMBERED_SET },
7645 // Used in CompileArrayPushCall. 7608 // Used in CompileArrayPushCall.
7646 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. 7609 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
7647 // Also used in KeyedStoreIC::GenerateGeneric. 7610 // Also used in KeyedStoreIC::GenerateGeneric.
7648 { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET }, 7611 { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET },
7649 // Used in CompileStoreGlobal. 7612 // Used in CompileStoreGlobal.
7650 { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET }, 7613 { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET },
7651 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. 7614 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
7652 { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET }, 7615 { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET },
7653 { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET }, 7616 { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET },
7654 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. 7617 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
8059 __ Pop(ra, t1, a1); 8022 __ Pop(ra, t1, a1);
8060 __ Ret(); 8023 __ Ret();
8061 } 8024 }
8062 8025
8063 8026
8064 #undef __ 8027 #undef __
8065 8028
8066 } } // namespace v8::internal 8029 } } // namespace v8::internal
8067 8030
8068 #endif // V8_TARGET_ARCH_MIPS 8031 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | src/mips/deoptimizer-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698