| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // x1: receiver | 119 // x1: receiver |
| 120 // x0: key | 120 // x0: key |
| 121 static Register registers[] = { x1, x0 }; | 121 static Register registers[] = { x1, x0 }; |
| 122 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 122 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 123 descriptor->register_params_ = registers; | 123 descriptor->register_params_ = registers; |
| 124 descriptor->deoptimization_handler_ = | 124 descriptor->deoptimization_handler_ = |
| 125 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 125 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( |
| 130 Isolate* isolate, |
| 131 CodeStubInterfaceDescriptor* descriptor) { |
| 132 // x1: receiver |
| 133 // x0: key |
| 134 static Register registers[] = { x1, x0 }; |
| 135 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 136 descriptor->register_params_ = registers; |
| 137 descriptor->deoptimization_handler_ = |
| 138 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
| 139 } |
| 140 |
| 141 |
| 129 void LoadFieldStub::InitializeInterfaceDescriptor( | 142 void LoadFieldStub::InitializeInterfaceDescriptor( |
| 130 Isolate* isolate, | 143 Isolate* isolate, |
| 131 CodeStubInterfaceDescriptor* descriptor) { | 144 CodeStubInterfaceDescriptor* descriptor) { |
| 132 // x0: receiver | 145 // x0: receiver |
| 133 static Register registers[] = { x0 }; | 146 static Register registers[] = { x0 }; |
| 134 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 147 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 135 descriptor->register_params_ = registers; | 148 descriptor->register_params_ = registers; |
| 136 descriptor->deoptimization_handler_ = NULL; | 149 descriptor->deoptimization_handler_ = NULL; |
| 137 } | 150 } |
| 138 | 151 |
| 139 | 152 |
| 140 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( | 153 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( |
| 141 Isolate* isolate, | 154 Isolate* isolate, |
| 142 CodeStubInterfaceDescriptor* descriptor) { | 155 CodeStubInterfaceDescriptor* descriptor) { |
| 143 // x1: receiver | 156 // x1: receiver |
| 144 static Register registers[] = { x1 }; | 157 static Register registers[] = { x1 }; |
| 145 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 158 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 146 descriptor->register_params_ = registers; | 159 descriptor->register_params_ = registers; |
| 147 descriptor->deoptimization_handler_ = NULL; | 160 descriptor->deoptimization_handler_ = NULL; |
| 148 } | 161 } |
| 149 | 162 |
| 150 | 163 |
| 164 void KeyedArrayCallStub::InitializeInterfaceDescriptor( |
| 165 Isolate* isolate, |
| 166 CodeStubInterfaceDescriptor* descriptor) { |
| 167 // x2: receiver |
| 168 static Register registers[] = { x2 }; |
| 169 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 170 descriptor->register_params_ = registers; |
| 171 descriptor->continuation_type_ = TAIL_CALL_CONTINUATION; |
| 172 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; |
| 173 descriptor->deoptimization_handler_ = |
| 174 FUNCTION_ADDR(KeyedCallIC_MissFromStubFailure); |
| 175 } |
| 176 |
| 177 |
| 151 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( | 178 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( |
| 152 Isolate* isolate, | 179 Isolate* isolate, |
| 153 CodeStubInterfaceDescriptor* descriptor) { | 180 CodeStubInterfaceDescriptor* descriptor) { |
| 154 // x2: receiver | 181 // x2: receiver |
| 155 // x1: key | 182 // x1: key |
| 156 // x0: value | 183 // x0: value |
| 157 static Register registers[] = { x2, x1, x0 }; | 184 static Register registers[] = { x2, x1, x0 }; |
| 158 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 185 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 159 descriptor->register_params_ = registers; | 186 descriptor->register_params_ = registers; |
| 160 descriptor->deoptimization_handler_ = | 187 descriptor->deoptimization_handler_ = |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate)); | 230 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate)); |
| 204 } | 231 } |
| 205 | 232 |
| 206 | 233 |
| 207 static void InitializeArrayConstructorDescriptor( | 234 static void InitializeArrayConstructorDescriptor( |
| 208 Isolate* isolate, | 235 Isolate* isolate, |
| 209 CodeStubInterfaceDescriptor* descriptor, | 236 CodeStubInterfaceDescriptor* descriptor, |
| 210 int constant_stack_parameter_count) { | 237 int constant_stack_parameter_count) { |
| 211 // x1: function | 238 // x1: function |
| 212 // x2: type info cell with elements kind | 239 // x2: type info cell with elements kind |
| 213 static Register registers[] = { x1, x2 }; | 240 // x0: number of arguments to the constructor function |
| 214 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 241 static Register registers_variable_args[] = { x1, x2, x0 }; |
| 215 if (constant_stack_parameter_count != 0) { | 242 static Register registers_no_args[] = { x1, x2 }; |
| 243 |
| 244 if (constant_stack_parameter_count == 0) { |
| 245 descriptor->register_param_count_ = |
| 246 sizeof(registers_no_args) / sizeof(registers_no_args[0]); |
| 247 descriptor->register_params_ = registers_no_args; |
| 248 } else { |
| 216 // stack param count needs (constructor pointer, and single argument) | 249 // stack param count needs (constructor pointer, and single argument) |
| 217 // x0: number of arguments to the constructor function | 250 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; |
| 218 descriptor->stack_parameter_count_ = x0; | 251 descriptor->stack_parameter_count_ = x0; |
| 252 descriptor->register_param_count_ = |
| 253 sizeof(registers_variable_args) / sizeof(registers_variable_args[0]); |
| 254 descriptor->register_params_ = registers_variable_args; |
| 219 } | 255 } |
| 256 |
| 220 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; | 257 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; |
| 221 descriptor->register_params_ = registers; | |
| 222 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; | 258 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; |
| 223 descriptor->deoptimization_handler_ = | 259 descriptor->deoptimization_handler_ = |
| 224 Runtime::FunctionForId(Runtime::kArrayConstructor)->entry; | 260 Runtime::FunctionForId(Runtime::kArrayConstructor)->entry; |
| 225 } | 261 } |
| 226 | 262 |
| 227 | 263 |
| 228 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 264 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 229 Isolate* isolate, | 265 Isolate* isolate, |
| 230 CodeStubInterfaceDescriptor* descriptor) { | 266 CodeStubInterfaceDescriptor* descriptor) { |
| 231 InitializeArrayConstructorDescriptor(isolate, descriptor, 0); | 267 InitializeArrayConstructorDescriptor(isolate, descriptor, 0); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 244 CodeStubInterfaceDescriptor* descriptor) { | 280 CodeStubInterfaceDescriptor* descriptor) { |
| 245 InitializeArrayConstructorDescriptor(isolate, descriptor, -1); | 281 InitializeArrayConstructorDescriptor(isolate, descriptor, -1); |
| 246 } | 282 } |
| 247 | 283 |
| 248 | 284 |
| 249 static void InitializeInternalArrayConstructorDescriptor( | 285 static void InitializeInternalArrayConstructorDescriptor( |
| 250 Isolate* isolate, | 286 Isolate* isolate, |
| 251 CodeStubInterfaceDescriptor* descriptor, | 287 CodeStubInterfaceDescriptor* descriptor, |
| 252 int constant_stack_parameter_count) { | 288 int constant_stack_parameter_count) { |
| 253 // x1: constructor function | 289 // x1: constructor function |
| 254 static Register registers[] = { x1 }; | 290 // x0: number of arguments to the constructor function |
| 255 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 291 static Register registers_variable_args[] = { x1, x0 }; |
| 256 if (constant_stack_parameter_count != 0) { | 292 static Register registers_no_args[] = { x1 }; |
| 293 |
| 294 if (constant_stack_parameter_count == 0) { |
| 295 descriptor->register_param_count_ = |
| 296 sizeof(registers_no_args) / sizeof(registers_no_args[0]); |
| 297 descriptor->register_params_ = registers_no_args; |
| 298 } else { |
| 257 // stack param count needs (constructor pointer, and single argument) | 299 // stack param count needs (constructor pointer, and single argument) |
| 258 // x0: number of arguments to the constructor function | 300 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; |
| 259 descriptor->stack_parameter_count_ = x0; | 301 descriptor->stack_parameter_count_ = x0; |
| 302 descriptor->register_param_count_ = |
| 303 sizeof(registers_variable_args) / sizeof(registers_variable_args[0]); |
| 304 descriptor->register_params_ = registers_variable_args; |
| 260 } | 305 } |
| 306 |
| 261 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; | 307 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; |
| 262 descriptor->register_params_ = registers; | |
| 263 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; | 308 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; |
| 264 descriptor->deoptimization_handler_ = | 309 descriptor->deoptimization_handler_ = |
| 265 Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry; | 310 Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry; |
| 266 } | 311 } |
| 267 | 312 |
| 268 | 313 |
| 269 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 314 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 270 Isolate* isolate, | 315 Isolate* isolate, |
| 271 CodeStubInterfaceDescriptor* descriptor) { | 316 CodeStubInterfaceDescriptor* descriptor) { |
| 272 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0); | 317 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0); |
| (...skipping 5188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5461 // TODO(jbramley): The ARM code leaves the (shifted) offset in r1. Why? | 5506 // TODO(jbramley): The ARM code leaves the (shifted) offset in r1. Why? |
| 5462 CEntryStub ces(1, kSaveFPRegs); | 5507 CEntryStub ces(1, kSaveFPRegs); |
| 5463 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 5508 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
| 5464 int parameter_count_offset = | 5509 int parameter_count_offset = |
| 5465 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 5510 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
| 5466 __ Ldr(x1, MemOperand(fp, parameter_count_offset)); | 5511 __ Ldr(x1, MemOperand(fp, parameter_count_offset)); |
| 5467 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 5512 if (function_mode_ == JS_FUNCTION_STUB_MODE) { |
| 5468 __ Add(x1, x1, 1); | 5513 __ Add(x1, x1, 1); |
| 5469 } | 5514 } |
| 5470 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 5515 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 5471 __ Add(__ StackPointer(), __ StackPointer(), | 5516 __ Drop(x1); |
| 5472 Operand(x1, LSL, kPointerSizeLog2)); | |
| 5473 // Return to IC Miss stub, continuation still on stack. | 5517 // Return to IC Miss stub, continuation still on stack. |
| 5474 __ Ret(); | 5518 __ Ret(); |
| 5475 } | 5519 } |
| 5476 | 5520 |
| 5477 | 5521 |
| 5522 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { |
| 5523 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); |
| 5524 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
| 5525 __ Mov(x1, x0); |
| 5526 int parameter_count_offset = |
| 5527 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
| 5528 __ Ldr(x0, MemOperand(fp, parameter_count_offset)); |
| 5529 // The parameter count above includes the receiver for the arguments passed to |
| 5530 // the deoptimization handler. Subtract the receiver for the parameter count |
| 5531 // for the call. |
| 5532 __ Sub(x0, x0, 1); |
| 5533 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 5534 ParameterCount argument_count(x0); |
| 5535 __ InvokeFunction( |
| 5536 x1, argument_count, JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 5537 } |
| 5538 |
| 5539 |
| 5478 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 5540 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| 5479 if (masm->isolate()->function_entry_hook() != NULL) { | 5541 if (masm->isolate()->function_entry_hook() != NULL) { |
| 5480 // TODO(all): This needs to be reliably consistent with | 5542 // TODO(all): This needs to be reliably consistent with |
| 5481 // kReturnAddressDistanceFromFunctionStart in ::Generate. | 5543 // kReturnAddressDistanceFromFunctionStart in ::Generate. |
| 5482 Assembler::BlockConstPoolScope no_const_pools(masm); | 5544 Assembler::BlockConstPoolScope no_const_pools(masm); |
| 5483 AllowStubCallsScope allow_stub_calls(masm, true); | 5545 AllowStubCallsScope allow_stub_calls(masm, true); |
| 5484 ProfileEntryHookStub stub; | 5546 ProfileEntryHookStub stub; |
| 5485 __ Push(lr); | 5547 __ Push(lr); |
| 5486 __ CallStub(&stub); | 5548 __ CallStub(&stub); |
| 5487 __ Pop(lr); | 5549 __ Pop(lr); |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5899 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset)); | 5961 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset)); |
| 5900 | 5962 |
| 5901 if (FLAG_debug_code) { | 5963 if (FLAG_debug_code) { |
| 5902 __ Ldr(x10, FieldMemOperand(x10, 0)); | 5964 __ Ldr(x10, FieldMemOperand(x10, 0)); |
| 5903 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, | 5965 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, |
| 5904 &normal_sequence); | 5966 &normal_sequence); |
| 5905 __ Assert(eq, kExpectedAllocationSiteInCell); | 5967 __ Assert(eq, kExpectedAllocationSiteInCell); |
| 5906 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset)); | 5968 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset)); |
| 5907 } | 5969 } |
| 5908 | 5970 |
| 5909 // Save the resulting elements kind in type info. | 5971 // Save the resulting elements kind in type info. We can't just store 'kind' |
| 5910 // TODO(jbramley): Tag and store at the same time. | 5972 // in the AllocationSite::transition_info field because elements kind is |
| 5911 __ SmiTag(x10, kind); | 5973 // restricted to a portion of the field; upper bits need to be left alone. |
| 5912 __ Ldr(x11, FieldMemOperand(type_info_cell, Cell::kValueOffset)); | 5974 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
| 5913 __ Str(x10, FieldMemOperand(x11, AllocationSite::kTransitionInfoOffset)); | 5975 __ Ldr(x11, FieldMemOperand(x10, AllocationSite::kTransitionInfoOffset)); |
| 5976 __ Add(x11, x11, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); |
| 5977 __ Str(x11, FieldMemOperand(x10, AllocationSite::kTransitionInfoOffset)); |
| 5914 | 5978 |
| 5915 __ Bind(&normal_sequence); | 5979 __ Bind(&normal_sequence); |
| 5916 int last_index = | 5980 int last_index = |
| 5917 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); | 5981 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
| 5918 for (int i = 0; i <= last_index; ++i) { | 5982 for (int i = 0; i <= last_index; ++i) { |
| 5919 Label next; | 5983 Label next; |
| 5920 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); | 5984 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); |
| 5921 // TODO(jbramley): Is this the best way to handle this? Can we make the | 5985 // TODO(jbramley): Is this the best way to handle this? Can we make the |
| 5922 // tail calls conditional, rather than hopping over each one? | 5986 // tail calls conditional, rather than hopping over each one? |
| 5923 __ CompareAndBranch(kind, candidate_kind, ne, &next); | 5987 __ CompareAndBranch(kind, candidate_kind, ne, &next); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6056 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset)); | 6120 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset)); |
| 6057 | 6121 |
| 6058 // If the type cell is undefined, or contains anything other than an | 6122 // If the type cell is undefined, or contains anything other than an |
| 6059 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 6123 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 6060 __ Ldr(x10, FieldMemOperand(kind, AllocationSite::kMapOffset)); | 6124 __ Ldr(x10, FieldMemOperand(kind, AllocationSite::kMapOffset)); |
| 6061 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &no_info); | 6125 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &no_info); |
| 6062 | 6126 |
| 6063 __ Ldrsw(kind, | 6127 __ Ldrsw(kind, |
| 6064 UntagSmiFieldMemOperand(kind, | 6128 UntagSmiFieldMemOperand(kind, |
| 6065 AllocationSite::kTransitionInfoOffset)); | 6129 AllocationSite::kTransitionInfoOffset)); |
| 6130 __ And(kind, kind, AllocationSite::ElementsKindBits::kMask); |
| 6066 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 6131 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 6067 | 6132 |
| 6068 __ Bind(&no_info); | 6133 __ Bind(&no_info); |
| 6069 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 6134 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 6070 } | 6135 } |
| 6071 | 6136 |
| 6072 | 6137 |
| 6073 void InternalArrayConstructorStub::GenerateCase( | 6138 void InternalArrayConstructorStub::GenerateCase( |
| 6074 MacroAssembler* masm, ElementsKind kind) { | 6139 MacroAssembler* masm, ElementsKind kind) { |
| 6075 Label zero_case, n_case; | 6140 Label zero_case, n_case; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6161 __ Bind(&fast_elements_case); | 6226 __ Bind(&fast_elements_case); |
| 6162 GenerateCase(masm, FAST_ELEMENTS); | 6227 GenerateCase(masm, FAST_ELEMENTS); |
| 6163 } | 6228 } |
| 6164 | 6229 |
| 6165 | 6230 |
| 6166 #undef __ | 6231 #undef __ |
| 6167 | 6232 |
| 6168 } } // namespace v8::internal | 6233 } } // namespace v8::internal |
| 6169 | 6234 |
| 6170 #endif // V8_TARGET_ARCH_A64 | 6235 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |