OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3292 case Token::BIT_NOT: | 3292 case Token::BIT_NOT: |
3293 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); | 3293 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); |
3294 break; | 3294 break; |
3295 default: | 3295 default: |
3296 UNREACHABLE(); | 3296 UNREACHABLE(); |
3297 } | 3297 } |
3298 } | 3298 } |
3299 | 3299 |
3300 | 3300 |
3301 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 3301 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
3302 // r0 holds the exception. | 3302 __ Throw(r0); |
3303 | |
3304 // Adjust this code if not the case. | |
3305 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
3306 | |
3307 // Drop the sp to the top of the handler. | |
3308 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | |
3309 __ ldr(sp, MemOperand(r3)); | |
3310 | |
3311 // Restore the next handler and frame pointer, discard handler state. | |
3312 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
3313 __ pop(r2); | |
3314 __ str(r2, MemOperand(r3)); | |
3315 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
3316 __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. | |
3317 | |
3318 // Before returning we restore the context from the frame pointer if | |
3319 // not NULL. The frame pointer is NULL in the exception handler of a | |
3320 // JS entry frame. | |
3321 __ cmp(fp, Operand(0, RelocInfo::NONE)); | |
3322 // Set cp to NULL if fp is NULL. | |
3323 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | |
3324 // Restore cp otherwise. | |
3325 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | |
3326 #ifdef DEBUG | |
3327 if (FLAG_debug_code) { | |
3328 __ mov(lr, Operand(pc)); | |
3329 } | |
3330 #endif | |
3331 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
3332 __ pop(pc); | |
3333 } | 3303 } |
3334 | 3304 |
3335 | 3305 |
3336 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 3306 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
3337 UncatchableExceptionType type) { | 3307 UncatchableExceptionType type) { |
3338 // Adjust this code if not the case. | 3308 __ ThrowUncatchable(type, r0); |
3339 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
3340 | |
3341 // Drop sp to the top stack handler. | |
3342 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | |
3343 __ ldr(sp, MemOperand(r3)); | |
3344 | |
3345 // Unwind the handlers until the ENTRY handler is found. | |
3346 Label loop, done; | |
3347 __ bind(&loop); | |
3348 // Load the type of the current stack handler. | |
3349 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
3350 __ ldr(r2, MemOperand(sp, kStateOffset)); | |
3351 __ cmp(r2, Operand(StackHandler::ENTRY)); | |
3352 __ b(eq, &done); | |
3353 // Fetch the next handler in the list. | |
3354 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
3355 __ ldr(sp, MemOperand(sp, kNextOffset)); | |
3356 __ jmp(&loop); | |
3357 __ bind(&done); | |
3358 | |
3359 // Set the top handler address to next handler past the current ENTRY handler. | |
3360 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
3361 __ pop(r2); | |
3362 __ str(r2, MemOperand(r3)); | |
3363 | |
3364 if (type == OUT_OF_MEMORY) { | |
3365 // Set external caught exception to false. | |
3366 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
3367 __ mov(r0, Operand(false, RelocInfo::NONE)); | |
3368 __ mov(r2, Operand(external_caught)); | |
3369 __ str(r0, MemOperand(r2)); | |
3370 | |
3371 // Set pending exception and r0 to out of memory exception. | |
3372 Failure* out_of_memory = Failure::OutOfMemoryException(); | |
3373 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | |
3374 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); | |
3375 __ str(r0, MemOperand(r2)); | |
3376 } | |
3377 | |
3378 // Stack layout at this point. See also StackHandlerConstants. | |
3379 // sp -> state (ENTRY) | |
3380 // fp | |
3381 // lr | |
3382 | |
3383 // Discard handler state (r2 is not used) and restore frame pointer. | |
3384 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
3385 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. | |
3386 // Before returning we restore the context from the frame pointer if | |
3387 // not NULL. The frame pointer is NULL in the exception handler of a | |
3388 // JS entry frame. | |
3389 __ cmp(fp, Operand(0, RelocInfo::NONE)); | |
3390 // Set cp to NULL if fp is NULL. | |
3391 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | |
3392 // Restore cp otherwise. | |
3393 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | |
3394 #ifdef DEBUG | |
3395 if (FLAG_debug_code) { | |
3396 __ mov(lr, Operand(pc)); | |
3397 } | |
3398 #endif | |
3399 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
3400 __ pop(pc); | |
3401 } | 3309 } |
3402 | 3310 |
3403 | 3311 |
3404 void CEntryStub::GenerateCore(MacroAssembler* masm, | 3312 void CEntryStub::GenerateCore(MacroAssembler* masm, |
3405 Label* throw_normal_exception, | 3313 Label* throw_normal_exception, |
3406 Label* throw_termination_exception, | 3314 Label* throw_termination_exception, |
3407 Label* throw_out_of_memory_exception, | 3315 Label* throw_out_of_memory_exception, |
3408 bool do_gc, | 3316 bool do_gc, |
3409 bool always_allocate) { | 3317 bool always_allocate) { |
3410 // r0: result parameter for PerformGC, if any | 3318 // r0: result parameter for PerformGC, if any |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3477 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 3385 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
3478 // Lower 2 bits of r2 are 0 iff r0 has failure tag. | 3386 // Lower 2 bits of r2 are 0 iff r0 has failure tag. |
3479 __ add(r2, r0, Operand(1)); | 3387 __ add(r2, r0, Operand(1)); |
3480 __ tst(r2, Operand(kFailureTagMask)); | 3388 __ tst(r2, Operand(kFailureTagMask)); |
3481 __ b(eq, &failure_returned); | 3389 __ b(eq, &failure_returned); |
3482 | 3390 |
3483 // Exit C frame and return. | 3391 // Exit C frame and return. |
3484 // r0:r1: result | 3392 // r0:r1: result |
3485 // sp: stack pointer | 3393 // sp: stack pointer |
3486 // fp: frame pointer | 3394 // fp: frame pointer |
3487 __ LeaveExitFrame(save_doubles_); | 3395 // Callee-saved register r4 still holds argc. |
| 3396 __ LeaveExitFrame(save_doubles_, r4); |
| 3397 __ mov(pc, lr); |
3488 | 3398 |
3489 // check if we should retry or throw exception | 3399 // check if we should retry or throw exception |
3490 Label retry; | 3400 Label retry; |
3491 __ bind(&failure_returned); | 3401 __ bind(&failure_returned); |
3492 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | 3402 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
3493 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 3403 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
3494 __ b(eq, &retry); | 3404 __ b(eq, &retry); |
3495 | 3405 |
3496 // Special handling of out of memory exceptions. | 3406 // Special handling of out of memory exceptions. |
3497 Failure* out_of_memory = Failure::OutOfMemoryException(); | 3407 Failure* out_of_memory = Failure::OutOfMemoryException(); |
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4256 | 4166 |
4257 // r1: previous index | 4167 // r1: previous index |
4258 // r3: encoding of subject string (1 if ascii, 0 if two_byte); | 4168 // r3: encoding of subject string (1 if ascii, 0 if two_byte); |
4259 // r7: code | 4169 // r7: code |
4260 // subject: Subject string | 4170 // subject: Subject string |
4261 // regexp_data: RegExp data (FixedArray) | 4171 // regexp_data: RegExp data (FixedArray) |
4262 // All checks done. Now push arguments for native regexp code. | 4172 // All checks done. Now push arguments for native regexp code. |
4263 __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2); | 4173 __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2); |
4264 | 4174 |
4265 static const int kRegExpExecuteArguments = 7; | 4175 static const int kRegExpExecuteArguments = 7; |
4266 __ push(lr); | 4176 static const int kParameterRegisters = 4; |
4267 __ PrepareCallCFunction(kRegExpExecuteArguments, r0); | 4177 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
4268 | 4178 |
4269 // Argument 7 (sp[8]): Indicate that this is a direct call from JavaScript. | 4179 // Stack pointer now points to cell where return address is to be written. |
| 4180 // Arguments are before that on the stack or in registers. |
| 4181 |
| 4182 // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript. |
4270 __ mov(r0, Operand(1)); | 4183 __ mov(r0, Operand(1)); |
4271 __ str(r0, MemOperand(sp, 2 * kPointerSize)); | 4184 __ str(r0, MemOperand(sp, 3 * kPointerSize)); |
4272 | 4185 |
4273 // Argument 6 (sp[4]): Start (high end) of backtracking stack memory area. | 4186 // Argument 6 (sp[8]): Start (high end) of backtracking stack memory area. |
4274 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); | 4187 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); |
4275 __ ldr(r0, MemOperand(r0, 0)); | 4188 __ ldr(r0, MemOperand(r0, 0)); |
4276 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); | 4189 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); |
4277 __ ldr(r2, MemOperand(r2, 0)); | 4190 __ ldr(r2, MemOperand(r2, 0)); |
4278 __ add(r0, r0, Operand(r2)); | 4191 __ add(r0, r0, Operand(r2)); |
| 4192 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
| 4193 |
| 4194 // Argument 5 (sp[4]): static offsets vector buffer. |
| 4195 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); |
4279 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 4196 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
4280 | 4197 |
4281 // Argument 5 (sp[0]): static offsets vector buffer. | |
4282 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); | |
4283 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | |
4284 | |
4285 // For arguments 4 and 3 get string length, calculate start of string data and | 4198 // For arguments 4 and 3 get string length, calculate start of string data and |
4286 // calculate the shift of the index (0 for ASCII and 1 for two byte). | 4199 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
4287 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); | 4200 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); |
4288 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 4201 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
4289 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 4202 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
4290 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4203 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4291 __ eor(r3, r3, Operand(1)); | 4204 __ eor(r3, r3, Operand(1)); |
4292 // Argument 4 (r3): End of string data | 4205 // Argument 4 (r3): End of string data |
4293 // Argument 3 (r2): Start of string data | 4206 // Argument 3 (r2): Start of string data |
4294 __ add(r2, r9, Operand(r1, LSL, r3)); | 4207 __ add(r2, r9, Operand(r1, LSL, r3)); |
4295 __ add(r3, r9, Operand(r0, LSL, r3)); | 4208 __ add(r3, r9, Operand(r0, LSL, r3)); |
4296 | 4209 |
4297 // Argument 2 (r1): Previous index. | 4210 // Argument 2 (r1): Previous index. |
4298 // Already there | 4211 // Already there |
4299 | 4212 |
4300 // Argument 1 (r0): Subject string. | 4213 // Argument 1 (r0): Subject string. |
4301 __ mov(r0, subject); | 4214 __ mov(r0, subject); |
4302 | 4215 |
4303 // Locate the code entry and call it. | 4216 // Locate the code entry and call it. |
4304 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4217 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
4305 __ CallCFunction(r7, kRegExpExecuteArguments); | 4218 DirectCEntryStub stub; |
4306 __ pop(lr); | 4219 stub.GenerateCall(masm, r7); |
| 4220 |
| 4221 __ LeaveExitFrame(false, no_reg); |
4307 | 4222 |
4308 // r0: result | 4223 // r0: result |
4309 // subject: subject string (callee saved) | 4224 // subject: subject string (callee saved) |
4310 // regexp_data: RegExp data (callee saved) | 4225 // regexp_data: RegExp data (callee saved) |
4311 // last_match_info_elements: Last match info elements (callee saved) | 4226 // last_match_info_elements: Last match info elements (callee saved) |
4312 | 4227 |
4313 // Check the result. | 4228 // Check the result. |
4314 Label success; | 4229 Label success; |
| 4230 |
4315 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); | 4231 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
4316 __ b(eq, &success); | 4232 __ b(eq, &success); |
4317 Label failure; | 4233 Label failure; |
4318 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 4234 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
4319 __ b(eq, &failure); | 4235 __ b(eq, &failure); |
4320 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 4236 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
4321 // If not exception it can only be retry. Handle that in the runtime system. | 4237 // If not exception it can only be retry. Handle that in the runtime system. |
4322 __ b(ne, &runtime); | 4238 __ b(ne, &runtime); |
4323 // Result must now be exception. If there is no pending exception already a | 4239 // Result must now be exception. If there is no pending exception already a |
4324 // stack overflow (on the backtrack stack) was detected in RegExp code but | 4240 // stack overflow (on the backtrack stack) was detected in RegExp code but |
4325 // haven't created the exception yet. Handle that in the runtime system. | 4241 // haven't created the exception yet. Handle that in the runtime system. |
4326 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 4242 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
4327 __ mov(r0, Operand(ExternalReference::the_hole_value_location())); | 4243 __ mov(r1, Operand(ExternalReference::the_hole_value_location())); |
4328 __ ldr(r0, MemOperand(r0, 0)); | |
4329 __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address))); | |
4330 __ ldr(r1, MemOperand(r1, 0)); | 4244 __ ldr(r1, MemOperand(r1, 0)); |
| 4245 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 4246 __ ldr(r0, MemOperand(r2, 0)); |
4331 __ cmp(r0, r1); | 4247 __ cmp(r0, r1); |
4332 __ b(eq, &runtime); | 4248 __ b(eq, &runtime); |
| 4249 |
| 4250 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. |
| 4251 |
| 4252 // Check if the exception is a termination. If so, throw as uncatchable. |
| 4253 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); |
| 4254 __ cmp(r0, ip); |
| 4255 Label termination_exception; |
| 4256 __ b(eq, &termination_exception); |
| 4257 |
| 4258 __ Throw(r0); // Expects thrown value in r0. |
| 4259 |
| 4260 __ bind(&termination_exception); |
| 4261 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. |
| 4262 |
4333 __ bind(&failure); | 4263 __ bind(&failure); |
4334 // For failure and exception return null. | 4264 // For failure and exception return null. |
4335 __ mov(r0, Operand(Factory::null_value())); | 4265 __ mov(r0, Operand(Factory::null_value())); |
4336 __ add(sp, sp, Operand(4 * kPointerSize)); | 4266 __ add(sp, sp, Operand(4 * kPointerSize)); |
4337 __ Ret(); | 4267 __ Ret(); |
4338 | 4268 |
4339 // Process the result from the native regexp code. | 4269 // Process the result from the native regexp code. |
4340 __ bind(&success); | 4270 __ bind(&success); |
4341 __ ldr(r1, | 4271 __ ldr(r1, |
4342 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 4272 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
(...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5946 | 5876 |
5947 void DirectCEntryStub::Generate(MacroAssembler* masm) { | 5877 void DirectCEntryStub::Generate(MacroAssembler* masm) { |
5948 __ ldr(pc, MemOperand(sp, 0)); | 5878 __ ldr(pc, MemOperand(sp, 0)); |
5949 } | 5879 } |
5950 | 5880 |
5951 | 5881 |
5952 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, | 5882 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
5953 ApiFunction *function) { | 5883 ApiFunction *function) { |
5954 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), | 5884 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
5955 RelocInfo::CODE_TARGET)); | 5885 RelocInfo::CODE_TARGET)); |
5956 // Push return address (accessible to GC through exit frame pc). | |
5957 __ mov(r2, | 5886 __ mov(r2, |
5958 Operand(ExternalReference(function, ExternalReference::DIRECT_CALL))); | 5887 Operand(ExternalReference(function, ExternalReference::DIRECT_CALL))); |
| 5888 // Push return address (accessible to GC through exit frame pc). |
5959 __ str(pc, MemOperand(sp, 0)); | 5889 __ str(pc, MemOperand(sp, 0)); |
5960 __ Jump(r2); // Call the api function. | 5890 __ Jump(r2); // Call the api function. |
5961 } | 5891 } |
5962 | 5892 |
5963 | 5893 |
| 5894 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
| 5895 Register target) { |
| 5896 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
| 5897 RelocInfo::CODE_TARGET)); |
| 5898 // Push return address (accessible to GC through exit frame pc). |
| 5899 __ str(pc, MemOperand(sp, 0)); |
| 5900 __ Jump(target); // Call the C++ function. |
| 5901 } |
| 5902 |
| 5903 |
5964 void GenerateFastPixelArrayLoad(MacroAssembler* masm, | 5904 void GenerateFastPixelArrayLoad(MacroAssembler* masm, |
5965 Register receiver, | 5905 Register receiver, |
5966 Register key, | 5906 Register key, |
5967 Register elements_map, | 5907 Register elements_map, |
5968 Register elements, | 5908 Register elements, |
5969 Register scratch1, | 5909 Register scratch1, |
5970 Register scratch2, | 5910 Register scratch2, |
5971 Register result, | 5911 Register result, |
5972 Label* not_pixel_array, | 5912 Label* not_pixel_array, |
5973 Label* key_not_smi, | 5913 Label* key_not_smi, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6026 __ SmiTag(r0, scratch1); | 5966 __ SmiTag(r0, scratch1); |
6027 __ Ret(); | 5967 __ Ret(); |
6028 } | 5968 } |
6029 | 5969 |
6030 | 5970 |
6031 #undef __ | 5971 #undef __ |
6032 | 5972 |
6033 } } // namespace v8::internal | 5973 } } // namespace v8::internal |
6034 | 5974 |
6035 #endif // V8_TARGET_ARCH_ARM | 5975 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |