| 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { | 97 void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { |
| 98 frame_state_->Save(masm); | 98 frame_state_->Save(masm); |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { | 102 void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
| 103 frame_state_->Restore(masm); | 103 frame_state_->Restore(masm); |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 void ICRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { | 107 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { |
| 108 masm->EnterInternalFrame(); | 108 masm->EnterInternalFrame(); |
| 109 } | 109 } |
| 110 | 110 |
| 111 | 111 |
| 112 void ICRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { | 112 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
| 113 masm->LeaveInternalFrame(); | 113 masm->LeaveInternalFrame(); |
| 114 } | 114 } |
| 115 | 115 |
| 116 | 116 |
| 117 // ------------------------------------------------------------------------- | 117 // ------------------------------------------------------------------------- |
| 118 // CodeGenState implementation. | 118 // CodeGenState implementation. |
| 119 | 119 |
| 120 CodeGenState::CodeGenState(CodeGenerator* owner) | 120 CodeGenState::CodeGenState(CodeGenerator* owner) |
| 121 : owner_(owner), | 121 : owner_(owner), |
| 122 destination_(NULL), | 122 destination_(NULL), |
| (...skipping 7273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7396 | 7396 |
| 7397 | 7397 |
| 7398 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 7398 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
| 7399 ASSERT_EQ(4, args->length()); | 7399 ASSERT_EQ(4, args->length()); |
| 7400 | 7400 |
| 7401 // Load the arguments on the stack and call the stub. | 7401 // Load the arguments on the stack and call the stub. |
| 7402 Load(args->at(0)); | 7402 Load(args->at(0)); |
| 7403 Load(args->at(1)); | 7403 Load(args->at(1)); |
| 7404 Load(args->at(2)); | 7404 Load(args->at(2)); |
| 7405 Load(args->at(3)); | 7405 Load(args->at(3)); |
| 7406 |
| 7406 RegExpExecStub stub; | 7407 RegExpExecStub stub; |
| 7407 Result result = frame_->CallStub(&stub, 4); | 7408 Result result = frame_->CallStub(&stub, 4); |
| 7408 frame_->Push(&result); | 7409 frame_->Push(&result); |
| 7409 } | 7410 } |
| 7410 | 7411 |
| 7411 | 7412 |
| 7412 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { | 7413 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { |
| 7413 // No stub. This code only occurs a few times in regexp.js. | |
| 7414 const int kMaxInlineLength = 100; | |
| 7415 ASSERT_EQ(3, args->length()); | 7414 ASSERT_EQ(3, args->length()); |
| 7415 |
| 7416 Load(args->at(0)); // Size of array, smi. | 7416 Load(args->at(0)); // Size of array, smi. |
| 7417 Load(args->at(1)); // "index" property value. | 7417 Load(args->at(1)); // "index" property value. |
| 7418 Load(args->at(2)); // "input" property value. | 7418 Load(args->at(2)); // "input" property value. |
| 7419 { | |
| 7420 VirtualFrame::SpilledScope spilled_scope; | |
| 7421 | 7419 |
| 7422 Label slowcase; | 7420 RegExpConstructResultStub stub; |
| 7423 Label done; | 7421 Result result = frame_->CallStub(&stub, 3); |
| 7424 __ mov(ebx, Operand(esp, kPointerSize * 2)); | 7422 frame_->Push(&result); |
| 7425 __ test(ebx, Immediate(kSmiTagMask)); | |
| 7426 __ j(not_zero, &slowcase); | |
| 7427 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); | |
| 7428 __ j(above, &slowcase); | |
| 7429 // Smi-tagging is equivalent to multiplying by 2. | |
| 7430 STATIC_ASSERT(kSmiTag == 0); | |
| 7431 STATIC_ASSERT(kSmiTagSize == 1); | |
| 7432 // Allocate RegExpResult followed by FixedArray with size in ebx. | |
| 7433 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] | |
| 7434 // Elements: [Map][Length][..elements..] | |
| 7435 __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize, | |
| 7436 times_half_pointer_size, | |
| 7437 ebx, // In: Number of elements (times 2, being a smi) | |
| 7438 eax, // Out: Start of allocation (tagged). | |
| 7439 ecx, // Out: End of allocation. | |
| 7440 edx, // Scratch register | |
| 7441 &slowcase, | |
| 7442 TAG_OBJECT); | |
| 7443 // eax: Start of allocated area, object-tagged. | |
| 7444 | |
| 7445 // Set JSArray map to global.regexp_result_map(). | |
| 7446 // Set empty properties FixedArray. | |
| 7447 // Set elements to point to FixedArray allocated right after the JSArray. | |
| 7448 // Interleave operations for better latency. | |
| 7449 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); | |
| 7450 __ mov(ecx, Immediate(FACTORY->empty_fixed_array())); | |
| 7451 __ lea(ebx, Operand(eax, JSRegExpResult::kSize)); | |
| 7452 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); | |
| 7453 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); | |
| 7454 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | |
| 7455 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); | |
| 7456 __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx); | |
| 7457 | |
| 7458 // Set input, index and length fields from arguments. | |
| 7459 __ pop(FieldOperand(eax, JSRegExpResult::kInputOffset)); | |
| 7460 __ pop(FieldOperand(eax, JSRegExpResult::kIndexOffset)); | |
| 7461 __ pop(ecx); | |
| 7462 __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx); | |
| 7463 | |
| 7464 // Fill out the elements FixedArray. | |
| 7465 // eax: JSArray. | |
| 7466 // ebx: FixedArray. | |
| 7467 // ecx: Number of elements in array, as smi. | |
| 7468 | |
| 7469 // Set map. | |
| 7470 __ mov(FieldOperand(ebx, HeapObject::kMapOffset), | |
| 7471 Immediate(FACTORY->fixed_array_map())); | |
| 7472 // Set length. | |
| 7473 __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx); | |
| 7474 // Fill contents of fixed-array with the-hole. | |
| 7475 __ SmiUntag(ecx); | |
| 7476 __ mov(edx, Immediate(FACTORY->the_hole_value())); | |
| 7477 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); | |
| 7478 // Fill fixed array elements with hole. | |
| 7479 // eax: JSArray. | |
| 7480 // ecx: Number of elements to fill. | |
| 7481 // ebx: Start of elements in FixedArray. | |
| 7482 // edx: the hole. | |
| 7483 Label loop; | |
| 7484 __ test(ecx, Operand(ecx)); | |
| 7485 __ bind(&loop); | |
| 7486 __ j(less_equal, &done); // Jump if ecx is negative or zero. | |
| 7487 __ sub(Operand(ecx), Immediate(1)); | |
| 7488 __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx); | |
| 7489 __ jmp(&loop); | |
| 7490 | |
| 7491 __ bind(&slowcase); | |
| 7492 __ CallRuntime(Runtime::kRegExpConstructResult, 3); | |
| 7493 | |
| 7494 __ bind(&done); | |
| 7495 } | |
| 7496 frame_->Forget(3); | |
| 7497 frame_->Push(eax); | |
| 7498 } | 7423 } |
| 7499 | 7424 |
| 7500 | 7425 |
| 7501 class DeferredSearchCache: public DeferredCode { | 7426 class DeferredSearchCache: public DeferredCode { |
| 7502 public: | 7427 public: |
| 7503 DeferredSearchCache(Register dst, Register cache, Register key) | 7428 DeferredSearchCache(Register dst, Register cache, Register key) |
| 7504 : dst_(dst), cache_(cache), key_(key) { | 7429 : dst_(dst), cache_(cache), key_(key) { |
| 7505 set_comment("[ DeferredSearchCache"); | 7430 set_comment("[ DeferredSearchCache"); |
| 7506 } | 7431 } |
| 7507 | 7432 |
| (...skipping 2577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10085 case ILLEGAL: | 10010 case ILLEGAL: |
| 10086 UNREACHABLE(); | 10011 UNREACHABLE(); |
| 10087 } | 10012 } |
| 10088 } | 10013 } |
| 10089 | 10014 |
| 10090 | 10015 |
| 10091 #undef __ | 10016 #undef __ |
| 10092 | 10017 |
| 10093 #define __ masm. | 10018 #define __ masm. |
| 10094 | 10019 |
| 10020 |
| 10021 static void MemCopyWrapper(void* dest, const void* src, size_t size) { |
| 10022 memcpy(dest, src, size); |
| 10023 } |
| 10024 |
| 10025 |
| 10095 MemCopyFunction CreateMemCopyFunction() { | 10026 MemCopyFunction CreateMemCopyFunction() { |
| 10096 size_t actual_size; | 10027 HandleScope scope; |
| 10097 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 10028 MacroAssembler masm(NULL, 1 * KB); |
| 10098 &actual_size, | |
| 10099 true)); | |
| 10100 CHECK(buffer); | |
| 10101 HandleScope handles; | |
| 10102 MacroAssembler masm(buffer, static_cast<int>(actual_size)); | |
| 10103 | 10029 |
| 10104 // Generated code is put into a fixed, unmovable, buffer, and not into | 10030 // Generated code is put into a fixed, unmovable, buffer, and not into |
| 10105 // the V8 heap. We can't, and don't, refer to any relocatable addresses | 10031 // the V8 heap. We can't, and don't, refer to any relocatable addresses |
| 10106 // (e.g. the JavaScript nan-object). | 10032 // (e.g. the JavaScript nan-object). |
| 10107 | 10033 |
| 10108 // 32-bit C declaration function calls pass arguments on stack. | 10034 // 32-bit C declaration function calls pass arguments on stack. |
| 10109 | 10035 |
| 10110 // Stack layout: | 10036 // Stack layout: |
| 10111 // esp[12]: Third argument, size. | 10037 // esp[12]: Third argument, size. |
| 10112 // esp[8]: Second argument, source pointer. | 10038 // esp[8]: Second argument, source pointer. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10186 __ add(Operand(src), Immediate(0x10)); | 10112 __ add(Operand(src), Immediate(0x10)); |
| 10187 __ movdqa(Operand(dst, 0), xmm0); | 10113 __ movdqa(Operand(dst, 0), xmm0); |
| 10188 __ add(Operand(dst), Immediate(0x10)); | 10114 __ add(Operand(dst), Immediate(0x10)); |
| 10189 __ bind(&move_less_16); | 10115 __ bind(&move_less_16); |
| 10190 | 10116 |
| 10191 // At most 15 bytes to copy. Copy 16 bytes at end of string. | 10117 // At most 15 bytes to copy. Copy 16 bytes at end of string. |
| 10192 __ and_(count, 0xF); | 10118 __ and_(count, 0xF); |
| 10193 __ movdqu(xmm0, Operand(src, count, times_1, -0x10)); | 10119 __ movdqu(xmm0, Operand(src, count, times_1, -0x10)); |
| 10194 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0); | 10120 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0); |
| 10195 | 10121 |
| 10122 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset)); |
| 10196 __ pop(esi); | 10123 __ pop(esi); |
| 10197 __ pop(edi); | 10124 __ pop(edi); |
| 10198 __ ret(0); | 10125 __ ret(0); |
| 10199 } | 10126 } |
| 10200 __ Align(16); | 10127 __ Align(16); |
| 10201 { | 10128 { |
| 10202 // Copy loop for unaligned source and aligned destination. | 10129 // Copy loop for unaligned source and aligned destination. |
| 10203 // If source is not aligned, we can't read it as efficiently. | 10130 // If source is not aligned, we can't read it as efficiently. |
| 10204 __ bind(&unaligned_source); | 10131 __ bind(&unaligned_source); |
| 10205 __ IncrementCounter(COUNTERS->memcopy_unaligned(), 1); | 10132 __ IncrementCounter(COUNTERS->memcopy_unaligned(), 1); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 10232 __ add(Operand(src), Immediate(0x10)); | 10159 __ add(Operand(src), Immediate(0x10)); |
| 10233 __ movdqa(Operand(dst, 0), xmm0); | 10160 __ movdqa(Operand(dst, 0), xmm0); |
| 10234 __ add(Operand(dst), Immediate(0x10)); | 10161 __ add(Operand(dst), Immediate(0x10)); |
| 10235 __ bind(&move_less_16); | 10162 __ bind(&move_less_16); |
| 10236 | 10163 |
| 10237 // At most 15 bytes to copy. Copy 16 bytes at end of string. | 10164 // At most 15 bytes to copy. Copy 16 bytes at end of string. |
| 10238 __ and_(count, 0x0F); | 10165 __ and_(count, 0x0F); |
| 10239 __ movdqu(xmm0, Operand(src, count, times_1, -0x10)); | 10166 __ movdqu(xmm0, Operand(src, count, times_1, -0x10)); |
| 10240 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0); | 10167 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0); |
| 10241 | 10168 |
| 10169 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset)); |
| 10242 __ pop(esi); | 10170 __ pop(esi); |
| 10243 __ pop(edi); | 10171 __ pop(edi); |
| 10244 __ ret(0); | 10172 __ ret(0); |
| 10245 } | 10173 } |
| 10246 | 10174 |
| 10247 } else { | 10175 } else { |
| 10248 __ IncrementCounter(COUNTERS->memcopy_noxmm(), 1); | 10176 __ IncrementCounter(COUNTERS->memcopy_noxmm(), 1); |
| 10249 // SSE2 not supported. Unlikely to happen in practice. | 10177 // SSE2 not supported. Unlikely to happen in practice. |
| 10250 __ push(edi); | 10178 __ push(edi); |
| 10251 __ push(esi); | 10179 __ push(esi); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 10275 __ mov(edx, count); | 10203 __ mov(edx, count); |
| 10276 count = edx; | 10204 count = edx; |
| 10277 __ shr(ecx, 2); // Make word count instead of byte count. | 10205 __ shr(ecx, 2); // Make word count instead of byte count. |
| 10278 __ rep_movs(); | 10206 __ rep_movs(); |
| 10279 | 10207 |
| 10280 // At most 3 bytes left to copy. Copy 4 bytes at end of string. | 10208 // At most 3 bytes left to copy. Copy 4 bytes at end of string. |
| 10281 __ and_(count, 3); | 10209 __ and_(count, 3); |
| 10282 __ mov(eax, Operand(src, count, times_1, -4)); | 10210 __ mov(eax, Operand(src, count, times_1, -4)); |
| 10283 __ mov(Operand(dst, count, times_1, -4), eax); | 10211 __ mov(Operand(dst, count, times_1, -4), eax); |
| 10284 | 10212 |
| 10213 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset)); |
| 10285 __ pop(esi); | 10214 __ pop(esi); |
| 10286 __ pop(edi); | 10215 __ pop(edi); |
| 10287 __ ret(0); | 10216 __ ret(0); |
| 10288 } | 10217 } |
| 10289 | 10218 |
| 10290 CodeDesc desc; | 10219 CodeDesc desc; |
| 10291 masm.GetCode(&desc); | 10220 masm.GetCode(&desc); |
| 10292 // Call the function from C++. | 10221 ASSERT(desc.reloc_size == 0); |
| 10293 return FUNCTION_CAST<MemCopyFunction>(buffer); | 10222 |
| 10223 // Copy the generated code into an executable chunk and return a pointer |
| 10224 // to the first instruction in it as a C++ function pointer. |
| 10225 LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE); |
| 10226 if (chunk == NULL) return &MemCopyWrapper; |
| 10227 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); |
| 10228 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); |
| 10229 return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress()); |
| 10294 } | 10230 } |
| 10295 | 10231 |
| 10296 #undef __ | 10232 #undef __ |
| 10297 | 10233 |
| 10298 } } // namespace v8::internal | 10234 } } // namespace v8::internal |
| 10299 | 10235 |
| 10300 #endif // V8_TARGET_ARCH_IA32 | 10236 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |