OLD | NEW |
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 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 // Subtract from 0 if source was negative. | 474 // Subtract from 0 if source was negative. |
475 __ subu(at, zero_reg, source_); | 475 __ subu(at, zero_reg, source_); |
476 __ Movn(source_, at, exponent); | 476 __ Movn(source_, at, exponent); |
477 | 477 |
478 // We have -1, 0 or 1, which we treat specially. Register source_ contains | 478 // We have -1, 0 or 1, which we treat specially. Register source_ contains |
479 // absolute value: it is either equal to 1 (special case of -1 and 1), | 479 // absolute value: it is either equal to 1 (special case of -1 and 1), |
480 // greater than 1 (not a special case) or less than 1 (special case of 0). | 480 // greater than 1 (not a special case) or less than 1 (special case of 0). |
481 __ Branch(¬_special, gt, source_, Operand(1)); | 481 __ Branch(¬_special, gt, source_, Operand(1)); |
482 | 482 |
483 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | 483 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). |
484 static const uint32_t exponent_word_for_1 = | 484 const uint32_t exponent_word_for_1 = |
485 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | 485 HeapNumber::kExponentBias << HeapNumber::kExponentShift; |
486 // Safe to use 'at' as dest reg here. | 486 // Safe to use 'at' as dest reg here. |
487 __ Or(at, exponent, Operand(exponent_word_for_1)); | 487 __ Or(at, exponent, Operand(exponent_word_for_1)); |
488 __ Movn(exponent, at, source_); // Write exp when source not 0. | 488 __ Movn(exponent, at, source_); // Write exp when source not 0. |
489 // 1, 0 and -1 all have 0 for the second word. | 489 // 1, 0 and -1 all have 0 for the second word. |
490 __ Ret(USE_DELAY_SLOT); | 490 __ Ret(USE_DELAY_SLOT); |
491 __ mov(mantissa, zero_reg); | 491 __ mov(mantissa, zero_reg); |
492 | 492 |
493 __ bind(¬_special); | 493 __ bind(¬_special); |
494 // Count leading zeros. | 494 // Count leading zeros. |
(...skipping 3919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4414 | 4414 |
4415 Register InstanceofStub::left() { return a0; } | 4415 Register InstanceofStub::left() { return a0; } |
4416 | 4416 |
4417 | 4417 |
4418 Register InstanceofStub::right() { return a1; } | 4418 Register InstanceofStub::right() { return a1; } |
4419 | 4419 |
4420 | 4420 |
4421 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 4421 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
4422 // The displacement is the offset of the last parameter (if any) | 4422 // The displacement is the offset of the last parameter (if any) |
4423 // relative to the frame pointer. | 4423 // relative to the frame pointer. |
4424 static const int kDisplacement = | 4424 const int kDisplacement = |
4425 StandardFrameConstants::kCallerSPOffset - kPointerSize; | 4425 StandardFrameConstants::kCallerSPOffset - kPointerSize; |
4426 | 4426 |
4427 // Check that the key is a smiGenerateReadElement. | 4427 // Check that the key is a smiGenerateReadElement. |
4428 Label slow; | 4428 Label slow; |
4429 __ JumpIfNotSmi(a1, &slow); | 4429 __ JumpIfNotSmi(a1, &slow); |
4430 | 4430 |
4431 // Check if the calling frame is an arguments adaptor frame. | 4431 // Check if the calling frame is an arguments adaptor frame. |
4432 Label adaptor; | 4432 Label adaptor; |
4433 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 4433 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
4434 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 4434 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4826 #ifdef V8_INTERPRETED_REGEXP | 4826 #ifdef V8_INTERPRETED_REGEXP |
4827 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 4827 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
4828 #else // V8_INTERPRETED_REGEXP | 4828 #else // V8_INTERPRETED_REGEXP |
4829 | 4829 |
4830 // Stack frame on entry. | 4830 // Stack frame on entry. |
4831 // sp[0]: last_match_info (expected JSArray) | 4831 // sp[0]: last_match_info (expected JSArray) |
4832 // sp[4]: previous index | 4832 // sp[4]: previous index |
4833 // sp[8]: subject string | 4833 // sp[8]: subject string |
4834 // sp[12]: JSRegExp object | 4834 // sp[12]: JSRegExp object |
4835 | 4835 |
4836 static const int kLastMatchInfoOffset = 0 * kPointerSize; | 4836 const int kLastMatchInfoOffset = 0 * kPointerSize; |
4837 static const int kPreviousIndexOffset = 1 * kPointerSize; | 4837 const int kPreviousIndexOffset = 1 * kPointerSize; |
4838 static const int kSubjectOffset = 2 * kPointerSize; | 4838 const int kSubjectOffset = 2 * kPointerSize; |
4839 static const int kJSRegExpOffset = 3 * kPointerSize; | 4839 const int kJSRegExpOffset = 3 * kPointerSize; |
4840 | 4840 |
4841 Isolate* isolate = masm->isolate(); | 4841 Isolate* isolate = masm->isolate(); |
4842 | 4842 |
4843 Label runtime, invoke_regexp; | 4843 Label runtime, invoke_regexp; |
4844 | 4844 |
4845 // Allocation of registers for this function. These are in callee save | 4845 // Allocation of registers for this function. These are in callee save |
4846 // registers and will be preserved by the call to the native RegExp code, as | 4846 // registers and will be preserved by the call to the native RegExp code, as |
4847 // this code is called using the normal C calling convention. When calling | 4847 // this code is called using the normal C calling convention. When calling |
4848 // directly from generated code the native RegExp code will not do a GC and | 4848 // directly from generated code the native RegExp code will not do a GC and |
4849 // therefore the content of these registers are safe to use after the call. | 4849 // therefore the content of these registers are safe to use after the call. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5038 // a1: previous index | 5038 // a1: previous index |
5039 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 5039 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); |
5040 // t9: code | 5040 // t9: code |
5041 // subject: Subject string | 5041 // subject: Subject string |
5042 // regexp_data: RegExp data (FixedArray) | 5042 // regexp_data: RegExp data (FixedArray) |
5043 // All checks done. Now push arguments for native regexp code. | 5043 // All checks done. Now push arguments for native regexp code. |
5044 __ IncrementCounter(isolate->counters()->regexp_entry_native(), | 5044 __ IncrementCounter(isolate->counters()->regexp_entry_native(), |
5045 1, a0, a2); | 5045 1, a0, a2); |
5046 | 5046 |
5047 // Isolates: note we add an additional parameter here (isolate pointer). | 5047 // Isolates: note we add an additional parameter here (isolate pointer). |
5048 static const int kRegExpExecuteArguments = 8; | 5048 const int kRegExpExecuteArguments = 8; |
5049 static const int kParameterRegisters = 4; | 5049 const int kParameterRegisters = 4; |
5050 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 5050 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
5051 | 5051 |
5052 // Stack pointer now points to cell where return address is to be written. | 5052 // Stack pointer now points to cell where return address is to be written. |
5053 // Arguments are before that on the stack or in registers, meaning we | 5053 // Arguments are before that on the stack or in registers, meaning we |
5054 // treat the return address as argument 5. Thus every argument after that | 5054 // treat the return address as argument 5. Thus every argument after that |
5055 // needs to be shifted back by 1. Since DirectCEntryStub will handle | 5055 // needs to be shifted back by 1. Since DirectCEntryStub will handle |
5056 // allocating space for the c argument slots, we don't need to calculate | 5056 // allocating space for the c argument slots, we don't need to calculate |
5057 // that into the argument positions on the stack. This is how the stack will | 5057 // that into the argument positions on the stack. This is how the stack will |
5058 // look (sp meaning the value of sp at this moment): | 5058 // look (sp meaning the value of sp at this moment): |
5059 // [sp + 4] - Argument 8 | 5059 // [sp + 4] - Argument 8 |
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5924 // Registers. | 5924 // Registers. |
5925 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5925 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
5926 // hash: hash of two character string | 5926 // hash: hash of two character string |
5927 // mask: capacity mask | 5927 // mask: capacity mask |
5928 // first_symbol_table_element: address of the first element of | 5928 // first_symbol_table_element: address of the first element of |
5929 // the symbol table | 5929 // the symbol table |
5930 // undefined: the undefined object | 5930 // undefined: the undefined object |
5931 // scratch: - | 5931 // scratch: - |
5932 | 5932 |
5933 // Perform a number of probes in the symbol table. | 5933 // Perform a number of probes in the symbol table. |
5934 static const int kProbes = 4; | 5934 const int kProbes = 4; |
5935 Label found_in_symbol_table; | 5935 Label found_in_symbol_table; |
5936 Label next_probe[kProbes]; | 5936 Label next_probe[kProbes]; |
5937 Register candidate = scratch5; // Scratch register contains candidate. | 5937 Register candidate = scratch5; // Scratch register contains candidate. |
5938 for (int i = 0; i < kProbes; i++) { | 5938 for (int i = 0; i < kProbes; i++) { |
5939 // Calculate entry in symbol table. | 5939 // Calculate entry in symbol table. |
5940 if (i > 0) { | 5940 if (i > 0) { |
5941 __ Addu(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); | 5941 __ Addu(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); |
5942 } else { | 5942 } else { |
5943 __ mov(candidate, hash); | 5943 __ mov(candidate, hash); |
5944 } | 5944 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6052 // sp[4]: from | 6052 // sp[4]: from |
6053 // sp[8]: string | 6053 // sp[8]: string |
6054 | 6054 |
6055 // This stub is called from the native-call %_SubString(...), so | 6055 // This stub is called from the native-call %_SubString(...), so |
6056 // nothing can be assumed about the arguments. It is tested that: | 6056 // nothing can be assumed about the arguments. It is tested that: |
6057 // "string" is a sequential string, | 6057 // "string" is a sequential string, |
6058 // both "from" and "to" are smis, and | 6058 // both "from" and "to" are smis, and |
6059 // 0 <= from <= to <= string.length. | 6059 // 0 <= from <= to <= string.length. |
6060 // If any of these assumptions fail, we call the runtime system. | 6060 // If any of these assumptions fail, we call the runtime system. |
6061 | 6061 |
6062 static const int kToOffset = 0 * kPointerSize; | 6062 const int kToOffset = 0 * kPointerSize; |
6063 static const int kFromOffset = 1 * kPointerSize; | 6063 const int kFromOffset = 1 * kPointerSize; |
6064 static const int kStringOffset = 2 * kPointerSize; | 6064 const int kStringOffset = 2 * kPointerSize; |
6065 | 6065 |
6066 __ lw(a2, MemOperand(sp, kToOffset)); | 6066 __ lw(a2, MemOperand(sp, kToOffset)); |
6067 __ lw(a3, MemOperand(sp, kFromOffset)); | 6067 __ lw(a3, MemOperand(sp, kFromOffset)); |
6068 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 6068 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
6069 STATIC_ASSERT(kSmiTag == 0); | 6069 STATIC_ASSERT(kSmiTag == 0); |
6070 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 6070 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
6071 | 6071 |
6072 // Utilize delay slots. SmiUntag doesn't emit a jump, everything else is | 6072 // Utilize delay slots. SmiUntag doesn't emit a jump, everything else is |
6073 // safe in this case. | 6073 // safe in this case. |
6074 __ UntagAndJumpIfNotSmi(a2, a2, &runtime); | 6074 __ UntagAndJumpIfNotSmi(a2, a2, &runtime); |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7349 __ Ret(USE_DELAY_SLOT); | 7349 __ Ret(USE_DELAY_SLOT); |
7350 __ mov(result, zero_reg); | 7350 __ mov(result, zero_reg); |
7351 } | 7351 } |
7352 | 7352 |
7353 | 7353 |
7354 struct AheadOfTimeWriteBarrierStubList { | 7354 struct AheadOfTimeWriteBarrierStubList { |
7355 Register object, value, address; | 7355 Register object, value, address; |
7356 RememberedSetAction action; | 7356 RememberedSetAction action; |
7357 }; | 7357 }; |
7358 | 7358 |
| 7359 #define REG(Name) { kRegister_ ## Name ## _Code } |
7359 | 7360 |
7360 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 7361 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
7361 // Used in RegExpExecStub. | 7362 // Used in RegExpExecStub. |
7362 { s2, s0, t3, EMIT_REMEMBERED_SET }, | 7363 { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET }, |
7363 { s2, a2, t3, EMIT_REMEMBERED_SET }, | 7364 { REG(s2), REG(a2), REG(t3), EMIT_REMEMBERED_SET }, |
7364 // Used in CompileArrayPushCall. | 7365 // Used in CompileArrayPushCall. |
7365 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | 7366 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. |
7366 // Also used in KeyedStoreIC::GenerateGeneric. | 7367 // Also used in KeyedStoreIC::GenerateGeneric. |
7367 { a3, t0, t1, EMIT_REMEMBERED_SET }, | 7368 { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET }, |
7368 // Used in CompileStoreGlobal. | 7369 // Used in CompileStoreGlobal. |
7369 { t0, a1, a2, OMIT_REMEMBERED_SET }, | 7370 { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET }, |
7370 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. | 7371 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. |
7371 { a1, a2, a3, EMIT_REMEMBERED_SET }, | 7372 { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET }, |
7372 { a3, a2, a1, EMIT_REMEMBERED_SET }, | 7373 { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET }, |
7373 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 7374 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
7374 { a2, a1, a3, EMIT_REMEMBERED_SET }, | 7375 { REG(a2), REG(a1), REG(a3), EMIT_REMEMBERED_SET }, |
7375 { a3, a1, a2, EMIT_REMEMBERED_SET }, | 7376 { REG(a3), REG(a1), REG(a2), EMIT_REMEMBERED_SET }, |
7376 // KeyedStoreStubCompiler::GenerateStoreFastElement. | 7377 // KeyedStoreStubCompiler::GenerateStoreFastElement. |
7377 { a3, a2, t0, EMIT_REMEMBERED_SET }, | 7378 { REG(a3), REG(a2), REG(t0), EMIT_REMEMBERED_SET }, |
7378 { a2, a3, t0, EMIT_REMEMBERED_SET }, | 7379 { REG(a2), REG(a3), REG(t0), EMIT_REMEMBERED_SET }, |
7379 // ElementsTransitionGenerator::GenerateSmiOnlyToObject | 7380 // ElementsTransitionGenerator::GenerateSmiOnlyToObject |
7380 // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble | 7381 // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble |
7381 // and ElementsTransitionGenerator::GenerateDoubleToObject | 7382 // and ElementsTransitionGenerator::GenerateDoubleToObject |
7382 { a2, a3, t5, EMIT_REMEMBERED_SET }, | 7383 { REG(a2), REG(a3), REG(t5), EMIT_REMEMBERED_SET }, |
7383 { a2, a3, t5, OMIT_REMEMBERED_SET }, | 7384 { REG(a2), REG(a3), REG(t5), OMIT_REMEMBERED_SET }, |
7384 // ElementsTransitionGenerator::GenerateDoubleToObject | 7385 // ElementsTransitionGenerator::GenerateDoubleToObject |
7385 { t2, a2, a0, EMIT_REMEMBERED_SET }, | 7386 { REG(t2), REG(a2), REG(a0), EMIT_REMEMBERED_SET }, |
7386 { a2, t2, t5, EMIT_REMEMBERED_SET }, | 7387 { REG(a2), REG(t2), REG(t5), EMIT_REMEMBERED_SET }, |
7387 // StoreArrayLiteralElementStub::Generate | 7388 // StoreArrayLiteralElementStub::Generate |
7388 { t1, a0, t2, EMIT_REMEMBERED_SET }, | 7389 { REG(t1), REG(a0), REG(t2), EMIT_REMEMBERED_SET }, |
7389 // Null termination. | 7390 // Null termination. |
7390 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} | 7391 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} |
7391 }; | 7392 }; |
7392 | 7393 |
| 7394 #undef REG |
| 7395 |
7393 | 7396 |
7394 bool RecordWriteStub::IsPregenerated() { | 7397 bool RecordWriteStub::IsPregenerated() { |
7395 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 7398 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
7396 !entry->object.is(no_reg); | 7399 !entry->object.is(no_reg); |
7397 entry++) { | 7400 entry++) { |
7398 if (object_.is(entry->object) && | 7401 if (object_.is(entry->object) && |
7399 value_.is(entry->value) && | 7402 value_.is(entry->value) && |
7400 address_.is(entry->address) && | 7403 address_.is(entry->address) && |
7401 remembered_set_action_ == entry->action && | 7404 remembered_set_action_ == entry->action && |
7402 save_fp_regs_mode_ == kDontSaveFPRegs) { | 7405 save_fp_regs_mode_ == kDontSaveFPRegs) { |
7403 return true; | 7406 return true; |
7404 } | 7407 } |
7405 } | 7408 } |
7406 return false; | 7409 return false; |
7407 } | 7410 } |
7408 | 7411 |
7409 | 7412 |
7410 bool StoreBufferOverflowStub::IsPregenerated() { | 7413 bool StoreBufferOverflowStub::IsPregenerated() { |
7411 return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated(); | 7414 return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated(); |
7412 } | 7415 } |
7413 | 7416 |
7414 | 7417 |
7415 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { | 7418 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { |
7416 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 7419 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
7417 stub1.GetCode()->set_is_pregenerated(true); | 7420 stub1.GetCode()->set_is_pregenerated(true); |
7418 } | 7421 } |
7419 | 7422 |
7420 | 7423 |
7421 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { | 7424 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { |
7422 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 7425 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
7423 !entry->object.is(no_reg); | 7426 !entry->object.is(no_reg); |
7424 entry++) { | 7427 entry++) { |
7425 RecordWriteStub stub(entry->object, | 7428 RecordWriteStub stub(entry->object, |
7426 entry->value, | 7429 entry->value, |
7427 entry->address, | 7430 entry->address, |
7428 entry->action, | 7431 entry->action, |
7429 kDontSaveFPRegs); | 7432 kDontSaveFPRegs); |
7430 stub.GetCode()->set_is_pregenerated(true); | 7433 stub.GetCode()->set_is_pregenerated(true); |
7431 } | 7434 } |
7432 } | 7435 } |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7686 __ Ret(USE_DELAY_SLOT); | 7689 __ Ret(USE_DELAY_SLOT); |
7687 __ mov(v0, a0); | 7690 __ mov(v0, a0); |
7688 } | 7691 } |
7689 | 7692 |
7690 | 7693 |
7691 #undef __ | 7694 #undef __ |
7692 | 7695 |
7693 } } // namespace v8::internal | 7696 } } // namespace v8::internal |
7694 | 7697 |
7695 #endif // V8_TARGET_ARCH_MIPS | 7698 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |