| 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 3042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3053 case Token::BIT_NOT: | 3053 case Token::BIT_NOT: |
| 3054 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); | 3054 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); |
| 3055 break; | 3055 break; |
| 3056 default: | 3056 default: |
| 3057 UNREACHABLE(); | 3057 UNREACHABLE(); |
| 3058 } | 3058 } |
| 3059 } | 3059 } |
| 3060 | 3060 |
| 3061 | 3061 |
| 3062 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 3062 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 3063 // r0 holds the exception. | 3063 __ Throw(r0); |
| 3064 | |
| 3065 // Adjust this code if not the case. | |
| 3066 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 3067 | |
| 3068 // Drop the sp to the top of the handler. | |
| 3069 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | |
| 3070 __ ldr(sp, MemOperand(r3)); | |
| 3071 | |
| 3072 // Restore the next handler and frame pointer, discard handler state. | |
| 3073 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 3074 __ pop(r2); | |
| 3075 __ str(r2, MemOperand(r3)); | |
| 3076 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
| 3077 __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. | |
| 3078 | |
| 3079 // Before returning we restore the context from the frame pointer if | |
| 3080 // not NULL. The frame pointer is NULL in the exception handler of a | |
| 3081 // JS entry frame. | |
| 3082 __ cmp(fp, Operand(0, RelocInfo::NONE)); | |
| 3083 // Set cp to NULL if fp is NULL. | |
| 3084 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | |
| 3085 // Restore cp otherwise. | |
| 3086 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | |
| 3087 #ifdef DEBUG | |
| 3088 if (FLAG_debug_code) { | |
| 3089 __ mov(lr, Operand(pc)); | |
| 3090 } | |
| 3091 #endif | |
| 3092 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 3093 __ pop(pc); | |
| 3094 } | 3064 } |
| 3095 | 3065 |
| 3096 | 3066 |
| 3097 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 3067 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 3098 UncatchableExceptionType type) { | 3068 UncatchableExceptionType type) { |
| 3099 // Adjust this code if not the case. | 3069 __ ThrowUncatchable(type, r0); |
| 3100 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 3101 | |
| 3102 // Drop sp to the top stack handler. | |
| 3103 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | |
| 3104 __ ldr(sp, MemOperand(r3)); | |
| 3105 | |
| 3106 // Unwind the handlers until the ENTRY handler is found. | |
| 3107 Label loop, done; | |
| 3108 __ bind(&loop); | |
| 3109 // Load the type of the current stack handler. | |
| 3110 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
| 3111 __ ldr(r2, MemOperand(sp, kStateOffset)); | |
| 3112 __ cmp(r2, Operand(StackHandler::ENTRY)); | |
| 3113 __ b(eq, &done); | |
| 3114 // Fetch the next handler in the list. | |
| 3115 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
| 3116 __ ldr(sp, MemOperand(sp, kNextOffset)); | |
| 3117 __ jmp(&loop); | |
| 3118 __ bind(&done); | |
| 3119 | |
| 3120 // Set the top handler address to next handler past the current ENTRY handler. | |
| 3121 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 3122 __ pop(r2); | |
| 3123 __ str(r2, MemOperand(r3)); | |
| 3124 | |
| 3125 if (type == OUT_OF_MEMORY) { | |
| 3126 // Set external caught exception to false. | |
| 3127 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
| 3128 __ mov(r0, Operand(false, RelocInfo::NONE)); | |
| 3129 __ mov(r2, Operand(external_caught)); | |
| 3130 __ str(r0, MemOperand(r2)); | |
| 3131 | |
| 3132 // Set pending exception and r0 to out of memory exception. | |
| 3133 Failure* out_of_memory = Failure::OutOfMemoryException(); | |
| 3134 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | |
| 3135 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); | |
| 3136 __ str(r0, MemOperand(r2)); | |
| 3137 } | |
| 3138 | |
| 3139 // Stack layout at this point. See also StackHandlerConstants. | |
| 3140 // sp -> state (ENTRY) | |
| 3141 // fp | |
| 3142 // lr | |
| 3143 | |
| 3144 // Discard handler state (r2 is not used) and restore frame pointer. | |
| 3145 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
| 3146 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. | |
| 3147 // Before returning we restore the context from the frame pointer if | |
| 3148 // not NULL. The frame pointer is NULL in the exception handler of a | |
| 3149 // JS entry frame. | |
| 3150 __ cmp(fp, Operand(0, RelocInfo::NONE)); | |
| 3151 // Set cp to NULL if fp is NULL. | |
| 3152 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | |
| 3153 // Restore cp otherwise. | |
| 3154 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | |
| 3155 #ifdef DEBUG | |
| 3156 if (FLAG_debug_code) { | |
| 3157 __ mov(lr, Operand(pc)); | |
| 3158 } | |
| 3159 #endif | |
| 3160 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 3161 __ pop(pc); | |
| 3162 } | 3070 } |
| 3163 | 3071 |
| 3164 | 3072 |
| 3165 void CEntryStub::GenerateCore(MacroAssembler* masm, | 3073 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 3166 Label* throw_normal_exception, | 3074 Label* throw_normal_exception, |
| 3167 Label* throw_termination_exception, | 3075 Label* throw_termination_exception, |
| 3168 Label* throw_out_of_memory_exception, | 3076 Label* throw_out_of_memory_exception, |
| 3169 bool do_gc, | 3077 bool do_gc, |
| 3170 bool always_allocate) { | 3078 bool always_allocate) { |
| 3171 // r0: result parameter for PerformGC, if any | 3079 // r0: result parameter for PerformGC, if any |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3238 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 3146 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| 3239 // Lower 2 bits of r2 are 0 iff r0 has failure tag. | 3147 // Lower 2 bits of r2 are 0 iff r0 has failure tag. |
| 3240 __ add(r2, r0, Operand(1)); | 3148 __ add(r2, r0, Operand(1)); |
| 3241 __ tst(r2, Operand(kFailureTagMask)); | 3149 __ tst(r2, Operand(kFailureTagMask)); |
| 3242 __ b(eq, &failure_returned); | 3150 __ b(eq, &failure_returned); |
| 3243 | 3151 |
| 3244 // Exit C frame and return. | 3152 // Exit C frame and return. |
| 3245 // r0:r1: result | 3153 // r0:r1: result |
| 3246 // sp: stack pointer | 3154 // sp: stack pointer |
| 3247 // fp: frame pointer | 3155 // fp: frame pointer |
| 3248 __ LeaveExitFrame(save_doubles_); | 3156 // Callee-saved register r4 still holds argc. |
| 3157 __ LeaveExitFrame(save_doubles_, r4); |
| 3158 __ mov(pc, lr); |
| 3249 | 3159 |
| 3250 // check if we should retry or throw exception | 3160 // check if we should retry or throw exception |
| 3251 Label retry; | 3161 Label retry; |
| 3252 __ bind(&failure_returned); | 3162 __ bind(&failure_returned); |
| 3253 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | 3163 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
| 3254 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 3164 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
| 3255 __ b(eq, &retry); | 3165 __ b(eq, &retry); |
| 3256 | 3166 |
| 3257 // Special handling of out of memory exceptions. | 3167 // Special handling of out of memory exceptions. |
| 3258 Failure* out_of_memory = Failure::OutOfMemoryException(); | 3168 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3286 // sp: stack pointer (restored as callee's sp after C call) | 3196 // sp: stack pointer (restored as callee's sp after C call) |
| 3287 // cp: current context (C callee-saved) | 3197 // cp: current context (C callee-saved) |
| 3288 | 3198 |
| 3289 // Result returned in r0 or r0+r1 by default. | 3199 // Result returned in r0 or r0+r1 by default. |
| 3290 | 3200 |
| 3291 // NOTE: Invocations of builtins may return failure objects | 3201 // NOTE: Invocations of builtins may return failure objects |
| 3292 // instead of a proper result. The builtin entry handles | 3202 // instead of a proper result. The builtin entry handles |
| 3293 // this by performing a garbage collection and retrying the | 3203 // this by performing a garbage collection and retrying the |
| 3294 // builtin once. | 3204 // builtin once. |
| 3295 | 3205 |
| 3206 // Compute the argv pointer in a callee-saved register. |
| 3207 __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 3208 __ sub(r6, r6, Operand(kPointerSize)); |
| 3209 |
| 3296 // Enter the exit frame that transitions from JavaScript to C++. | 3210 // Enter the exit frame that transitions from JavaScript to C++. |
| 3297 __ EnterExitFrame(save_doubles_); | 3211 __ EnterExitFrame(save_doubles_); |
| 3298 | 3212 |
| 3213 // Setup argc and the builtin function in callee-saved registers. |
| 3214 __ mov(r4, Operand(r0)); |
| 3215 __ mov(r5, Operand(r1)); |
| 3216 |
| 3299 // r4: number of arguments (C callee-saved) | 3217 // r4: number of arguments (C callee-saved) |
| 3300 // r5: pointer to builtin function (C callee-saved) | 3218 // r5: pointer to builtin function (C callee-saved) |
| 3301 // r6: pointer to first argument (C callee-saved) | 3219 // r6: pointer to first argument (C callee-saved) |
| 3302 | 3220 |
| 3303 Label throw_normal_exception; | 3221 Label throw_normal_exception; |
| 3304 Label throw_termination_exception; | 3222 Label throw_termination_exception; |
| 3305 Label throw_out_of_memory_exception; | 3223 Label throw_out_of_memory_exception; |
| 3306 | 3224 |
| 3307 // Call into the runtime system. | 3225 // Call into the runtime system. |
| 3308 GenerateCore(masm, | 3226 GenerateCore(masm, |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4009 | 3927 |
| 4010 // r1: previous index | 3928 // r1: previous index |
| 4011 // r3: encoding of subject string (1 if ascii, 0 if two_byte); | 3929 // r3: encoding of subject string (1 if ascii, 0 if two_byte); |
| 4012 // r7: code | 3930 // r7: code |
| 4013 // subject: Subject string | 3931 // subject: Subject string |
| 4014 // regexp_data: RegExp data (FixedArray) | 3932 // regexp_data: RegExp data (FixedArray) |
| 4015 // All checks done. Now push arguments for native regexp code. | 3933 // All checks done. Now push arguments for native regexp code. |
| 4016 __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2); | 3934 __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2); |
| 4017 | 3935 |
| 4018 static const int kRegExpExecuteArguments = 7; | 3936 static const int kRegExpExecuteArguments = 7; |
| 4019 __ push(lr); | 3937 static const int kParameterRegisters = 4; |
| 4020 __ PrepareCallCFunction(kRegExpExecuteArguments, r0); | 3938 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
| 4021 | 3939 |
| 4022 // Argument 7 (sp[8]): Indicate that this is a direct call from JavaScript. | 3940 // Stack pointer now points to cell where return address is to be written. |
| 3941 // Arguments are before that on the stack or in registers. |
| 3942 |
| 3943 // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript. |
| 4023 __ mov(r0, Operand(1)); | 3944 __ mov(r0, Operand(1)); |
| 4024 __ str(r0, MemOperand(sp, 2 * kPointerSize)); | 3945 __ str(r0, MemOperand(sp, 3 * kPointerSize)); |
| 4025 | 3946 |
| 4026 // Argument 6 (sp[4]): Start (high end) of backtracking stack memory area. | 3947 // Argument 6 (sp[8]): Start (high end) of backtracking stack memory area. |
| 4027 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); | 3948 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); |
| 4028 __ ldr(r0, MemOperand(r0, 0)); | 3949 __ ldr(r0, MemOperand(r0, 0)); |
| 4029 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); | 3950 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); |
| 4030 __ ldr(r2, MemOperand(r2, 0)); | 3951 __ ldr(r2, MemOperand(r2, 0)); |
| 4031 __ add(r0, r0, Operand(r2)); | 3952 __ add(r0, r0, Operand(r2)); |
| 3953 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
| 3954 |
| 3955 // Argument 5 (sp[4]): static offsets vector buffer. |
| 3956 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); |
| 4032 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 3957 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
| 4033 | 3958 |
| 4034 // Argument 5 (sp[0]): static offsets vector buffer. | |
| 4035 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); | |
| 4036 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | |
| 4037 | |
| 4038 // For arguments 4 and 3 get string length, calculate start of string data and | 3959 // For arguments 4 and 3 get string length, calculate start of string data and |
| 4039 // calculate the shift of the index (0 for ASCII and 1 for two byte). | 3960 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
| 4040 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); | 3961 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); |
| 4041 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 3962 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
| 4042 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 3963 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
| 4043 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 3964 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 4044 __ eor(r3, r3, Operand(1)); | 3965 __ eor(r3, r3, Operand(1)); |
| 4045 // Argument 4 (r3): End of string data | 3966 // Argument 4 (r3): End of string data |
| 4046 // Argument 3 (r2): Start of string data | 3967 // Argument 3 (r2): Start of string data |
| 4047 __ add(r2, r9, Operand(r1, LSL, r3)); | 3968 __ add(r2, r9, Operand(r1, LSL, r3)); |
| 4048 __ add(r3, r9, Operand(r0, LSL, r3)); | 3969 __ add(r3, r9, Operand(r0, LSL, r3)); |
| 4049 | 3970 |
| 4050 // Argument 2 (r1): Previous index. | 3971 // Argument 2 (r1): Previous index. |
| 4051 // Already there | 3972 // Already there |
| 4052 | 3973 |
| 4053 // Argument 1 (r0): Subject string. | 3974 // Argument 1 (r0): Subject string. |
| 4054 __ mov(r0, subject); | 3975 __ mov(r0, subject); |
| 4055 | 3976 |
| 4056 // Locate the code entry and call it. | 3977 // Locate the code entry and call it. |
| 4057 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); | 3978 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 4058 __ CallCFunction(r7, kRegExpExecuteArguments); | 3979 DirectCEntryStub stub; |
| 4059 __ pop(lr); | 3980 stub.GenerateCall(masm, r7); |
| 3981 |
| 3982 __ LeaveExitFrame(false, no_reg); |
| 4060 | 3983 |
| 4061 // r0: result | 3984 // r0: result |
| 4062 // subject: subject string (callee saved) | 3985 // subject: subject string (callee saved) |
| 4063 // regexp_data: RegExp data (callee saved) | 3986 // regexp_data: RegExp data (callee saved) |
| 4064 // last_match_info_elements: Last match info elements (callee saved) | 3987 // last_match_info_elements: Last match info elements (callee saved) |
| 4065 | 3988 |
| 4066 // Check the result. | 3989 // Check the result. |
| 4067 Label success; | 3990 Label success; |
| 3991 |
| 4068 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); | 3992 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
| 4069 __ b(eq, &success); | 3993 __ b(eq, &success); |
| 4070 Label failure; | 3994 Label failure; |
| 4071 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 3995 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
| 4072 __ b(eq, &failure); | 3996 __ b(eq, &failure); |
| 4073 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 3997 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
| 4074 // If not exception it can only be retry. Handle that in the runtime system. | 3998 // If not exception it can only be retry. Handle that in the runtime system. |
| 4075 __ b(ne, &runtime); | 3999 __ b(ne, &runtime); |
| 4076 // Result must now be exception. If there is no pending exception already a | 4000 // Result must now be exception. If there is no pending exception already a |
| 4077 // stack overflow (on the backtrack stack) was detected in RegExp code but | 4001 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 4078 // haven't created the exception yet. Handle that in the runtime system. | 4002 // haven't created the exception yet. Handle that in the runtime system. |
| 4079 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 4003 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 4080 __ mov(r0, Operand(ExternalReference::the_hole_value_location())); | 4004 __ mov(r1, Operand(ExternalReference::the_hole_value_location())); |
| 4081 __ ldr(r0, MemOperand(r0, 0)); | |
| 4082 __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address))); | |
| 4083 __ ldr(r1, MemOperand(r1, 0)); | 4005 __ ldr(r1, MemOperand(r1, 0)); |
| 4006 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 4007 __ ldr(r0, MemOperand(r2, 0)); |
| 4084 __ cmp(r0, r1); | 4008 __ cmp(r0, r1); |
| 4085 __ b(eq, &runtime); | 4009 __ b(eq, &runtime); |
| 4010 |
| 4011 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. |
| 4012 |
| 4013 // Check if the exception is a termination. If so, throw as uncatchable. |
| 4014 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); |
| 4015 __ cmp(r0, ip); |
| 4016 Label termination_exception; |
| 4017 __ b(eq, &termination_exception); |
| 4018 |
| 4019 __ Throw(r0); // Expects thrown value in r0. |
| 4020 |
| 4021 __ bind(&termination_exception); |
| 4022 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. |
| 4023 |
| 4086 __ bind(&failure); | 4024 __ bind(&failure); |
| 4087 // For failure and exception return null. | 4025 // For failure and exception return null. |
| 4088 __ mov(r0, Operand(Factory::null_value())); | 4026 __ mov(r0, Operand(Factory::null_value())); |
| 4089 __ add(sp, sp, Operand(4 * kPointerSize)); | 4027 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 4090 __ Ret(); | 4028 __ Ret(); |
| 4091 | 4029 |
| 4092 // Process the result from the native regexp code. | 4030 // Process the result from the native regexp code. |
| 4093 __ bind(&success); | 4031 __ bind(&success); |
| 4094 __ ldr(r1, | 4032 __ ldr(r1, |
| 4095 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 4033 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
| (...skipping 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5691 // Compute the entry point of the rewritten stub. | 5629 // Compute the entry point of the rewritten stub. |
| 5692 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 5630 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 5693 // Restore registers. | 5631 // Restore registers. |
| 5694 __ pop(lr); | 5632 __ pop(lr); |
| 5695 __ pop(r0); | 5633 __ pop(r0); |
| 5696 __ pop(r1); | 5634 __ pop(r1); |
| 5697 __ Jump(r2); | 5635 __ Jump(r2); |
| 5698 } | 5636 } |
| 5699 | 5637 |
| 5700 | 5638 |
| 5639 void DirectCEntryStub::Generate(MacroAssembler* masm) { |
| 5640 __ ldr(pc, MemOperand(sp, 0)); |
| 5641 } |
| 5642 |
| 5643 |
| 5644 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
| 5645 ApiFunction *function) { |
| 5646 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
| 5647 RelocInfo::CODE_TARGET)); |
| 5648 __ mov(r2, |
| 5649 Operand(ExternalReference(function, ExternalReference::DIRECT_CALL))); |
| 5650 // Push return address (accessible to GC through exit frame pc). |
| 5651 __ str(pc, MemOperand(sp, 0)); |
| 5652 __ Jump(r2); // Call the api function. |
| 5653 } |
| 5654 |
| 5655 |
| 5656 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
| 5657 Register target) { |
| 5658 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
| 5659 RelocInfo::CODE_TARGET)); |
| 5660 // Push return address (accessible to GC through exit frame pc). |
| 5661 __ str(pc, MemOperand(sp, 0)); |
| 5662 __ Jump(target); // Call the C++ function. |
| 5663 } |
| 5664 |
| 5665 |
| 5701 #undef __ | 5666 #undef __ |
| 5702 | 5667 |
| 5703 } } // namespace v8::internal | 5668 } } // namespace v8::internal |
| 5704 | 5669 |
| 5705 #endif // V8_TARGET_ARCH_ARM | 5670 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |