OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #include "src/code-stub-assembler.h" | 7 #include "src/code-stub-assembler.h" |
8 #include "src/interface-descriptors.h" | 8 #include "src/interface-descriptors.h" |
9 #include "src/macro-assembler.h" | 9 #include "src/macro-assembler.h" |
10 | 10 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 Label runtime(&assembler, CodeStubAssembler::Label::kDeferred); | 134 Label runtime(&assembler, CodeStubAssembler::Label::kDeferred); |
135 Node* elements = assembler.LoadElements(object); | 135 Node* elements = assembler.LoadElements(object); |
136 elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS, | 136 elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS, |
137 key, &runtime); | 137 key, &runtime); |
138 assembler.Return(elements); | 138 assembler.Return(elements); |
139 | 139 |
140 assembler.Bind(&runtime); | 140 assembler.Bind(&runtime); |
141 assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key); | 141 assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key); |
142 } | 142 } |
143 | 143 |
| 144 namespace { |
| 145 |
| 146 void Generate_NewArgumentsElements(CodeStubAssembler* assembler, |
| 147 compiler::Node* frame, |
| 148 compiler::Node* length) { |
| 149 typedef CodeStubAssembler::Label Label; |
| 150 typedef CodeStubAssembler::Variable Variable; |
| 151 typedef compiler::Node Node; |
| 152 |
| 153 // Check if we can allocate in new space. |
| 154 ElementsKind kind = FAST_ELEMENTS; |
| 155 int max_elements = FixedArray::GetMaxLengthForNewSpaceAllocation(kind); |
| 156 Label if_newspace(assembler), if_oldspace(assembler, Label::kDeferred); |
| 157 assembler->Branch(assembler->IntPtrLessThan( |
| 158 length, assembler->IntPtrConstant(max_elements)), |
| 159 &if_newspace, &if_oldspace); |
| 160 |
| 161 assembler->Bind(&if_newspace); |
| 162 { |
| 163 // Prefer EmptyFixedArray in case of non-positive {length} (the {length} |
| 164 // can be negative here for rest parameters). |
| 165 Label if_empty(assembler), if_notempty(assembler); |
| 166 assembler->Branch( |
| 167 assembler->IntPtrLessThanOrEqual(length, assembler->IntPtrConstant(0)), |
| 168 &if_empty, &if_notempty); |
| 169 |
| 170 assembler->Bind(&if_empty); |
| 171 assembler->Return(assembler->EmptyFixedArrayConstant()); |
| 172 |
| 173 assembler->Bind(&if_notempty); |
| 174 { |
| 175 // Allocate a FixedArray in new space. |
| 176 Node* result = assembler->AllocateFixedArray( |
| 177 kind, length, CodeStubAssembler::INTPTR_PARAMETERS); |
| 178 |
| 179 // Compute the effective {offset} into the {frame}. |
| 180 Node* offset = assembler->IntPtrAdd(length, assembler->IntPtrConstant(1)); |
| 181 |
| 182 // Copy the parameters from {frame} (starting at {offset}) to {result}. |
| 183 Variable var_index(assembler, MachineType::PointerRepresentation()); |
| 184 Label loop(assembler, &var_index), done_loop(assembler); |
| 185 var_index.Bind(assembler->IntPtrConstant(0)); |
| 186 assembler->Goto(&loop); |
| 187 assembler->Bind(&loop); |
| 188 { |
| 189 // Load the current {index}. |
| 190 Node* index = var_index.value(); |
| 191 |
| 192 // Check if we are done. |
| 193 assembler->GotoIf(assembler->WordEqual(index, length), &done_loop); |
| 194 |
| 195 // Load the parameter at the given {index}. |
| 196 Node* value = assembler->Load( |
| 197 MachineType::AnyTagged(), frame, |
| 198 assembler->WordShl(assembler->IntPtrSub(offset, index), |
| 199 assembler->IntPtrConstant(kPointerSizeLog2))); |
| 200 |
| 201 // Store the {value} into the {result}. |
| 202 assembler->StoreFixedArrayElement(result, index, value, |
| 203 SKIP_WRITE_BARRIER, 0, |
| 204 CodeStubAssembler::INTPTR_PARAMETERS); |
| 205 |
| 206 // Continue with next {index}. |
| 207 var_index.Bind( |
| 208 assembler->IntPtrAdd(index, assembler->IntPtrConstant(1))); |
| 209 assembler->Goto(&loop); |
| 210 } |
| 211 |
| 212 assembler->Bind(&done_loop); |
| 213 assembler->Return(result); |
| 214 } |
| 215 } |
| 216 |
| 217 assembler->Bind(&if_oldspace); |
| 218 { |
| 219 // Allocate in old space (or large object space). |
| 220 assembler->TailCallRuntime( |
| 221 Runtime::kNewArgumentsElements, assembler->NoContextConstant(), |
| 222 assembler->BitcastWordToTagged(frame), assembler->SmiFromWord(length)); |
| 223 } |
| 224 } |
| 225 |
| 226 } // namespace |
| 227 |
| 228 void Builtins::Generate_NewUnmappedArgumentsElements( |
| 229 compiler::CodeAssemblerState* state) { |
| 230 typedef CodeStubAssembler::Label Label; |
| 231 typedef CodeStubAssembler::Variable Variable; |
| 232 typedef compiler::Node Node; |
| 233 typedef NewArgumentsElementsDescriptor Descriptor; |
| 234 CodeStubAssembler assembler(state); |
| 235 |
| 236 Node* formal_parameter_count = |
| 237 assembler.Parameter(Descriptor::kFormalParameterCount); |
| 238 |
| 239 // Determine the frame that holds the parameters. |
| 240 Label done(&assembler); |
| 241 Variable var_frame(&assembler, MachineType::PointerRepresentation()), |
| 242 var_length(&assembler, MachineType::PointerRepresentation()); |
| 243 var_frame.Bind(assembler.LoadParentFramePointer()); |
| 244 var_length.Bind(formal_parameter_count); |
| 245 Node* parent_frame = assembler.Load( |
| 246 MachineType::Pointer(), var_frame.value(), |
| 247 assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset)); |
| 248 Node* parent_frame_type = |
| 249 assembler.Load(MachineType::AnyTagged(), parent_frame, |
| 250 assembler.IntPtrConstant( |
| 251 CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 252 assembler.GotoUnless( |
| 253 assembler.WordEqual( |
| 254 parent_frame_type, |
| 255 assembler.SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))), |
| 256 &done); |
| 257 { |
| 258 // Determine the length from the ArgumentsAdaptorFrame. |
| 259 Node* length = assembler.LoadAndUntagSmi( |
| 260 parent_frame, ArgumentsAdaptorFrameConstants::kLengthOffset); |
| 261 |
| 262 // Take the arguments from the ArgumentsAdaptorFrame. |
| 263 var_frame.Bind(parent_frame); |
| 264 var_length.Bind(length); |
| 265 } |
| 266 assembler.Goto(&done); |
| 267 |
| 268 // Allocate the actual FixedArray for the elements. |
| 269 assembler.Bind(&done); |
| 270 Generate_NewArgumentsElements(&assembler, var_frame.value(), |
| 271 var_length.value()); |
| 272 } |
| 273 |
| 274 void Builtins::Generate_NewRestParameterElements( |
| 275 compiler::CodeAssemblerState* state) { |
| 276 typedef CodeStubAssembler::Label Label; |
| 277 typedef compiler::Node Node; |
| 278 typedef NewArgumentsElementsDescriptor Descriptor; |
| 279 CodeStubAssembler assembler(state); |
| 280 |
| 281 Node* formal_parameter_count = |
| 282 assembler.Parameter(Descriptor::kFormalParameterCount); |
| 283 |
| 284 // Check if we have an ArgumentsAdaptorFrame, as we will only have rest |
| 285 // parameters in that case. |
| 286 Label if_empty(&assembler); |
| 287 Node* frame = assembler.Load( |
| 288 MachineType::Pointer(), assembler.LoadParentFramePointer(), |
| 289 assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset)); |
| 290 Node* frame_type = |
| 291 assembler.Load(MachineType::AnyTagged(), frame, |
| 292 assembler.IntPtrConstant( |
| 293 CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 294 assembler.GotoUnless( |
| 295 assembler.WordEqual(frame_type, assembler.SmiConstant(Smi::FromInt( |
| 296 StackFrame::ARGUMENTS_ADAPTOR))), |
| 297 &if_empty); |
| 298 |
| 299 // Determine the length from the ArgumentsAdaptorFrame. |
| 300 Node* frame_length = assembler.LoadAndUntagSmi( |
| 301 frame, ArgumentsAdaptorFrameConstants::kLengthOffset); |
| 302 |
| 303 // Compute the actual rest parameter length (may be negative). |
| 304 Node* length = assembler.IntPtrSub(frame_length, formal_parameter_count); |
| 305 |
| 306 // Allocate the actual FixedArray for the elements. |
| 307 Generate_NewArgumentsElements(&assembler, frame, length); |
| 308 |
| 309 // No rest parameters, return an empty FixedArray. |
| 310 assembler.Bind(&if_empty); |
| 311 assembler.Return(assembler.EmptyFixedArrayConstant()); |
| 312 } |
| 313 |
144 } // namespace internal | 314 } // namespace internal |
145 } // namespace v8 | 315 } // namespace v8 |
OLD | NEW |