• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h"
7 #include "src/code-stub-assembler.h"
8 #include "src/counters.h"
9 #include "src/interface-descriptors.h"
10 #include "src/macro-assembler.h"
11 #include "src/objects-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 
BUILTIN(Illegal)16 BUILTIN(Illegal) {
17   UNREACHABLE();
18   return isolate->heap()->undefined_value();  // Make compiler happy.
19 }
20 
BUILTIN(EmptyFunction)21 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
22 
BUILTIN(UnsupportedThrower)23 BUILTIN(UnsupportedThrower) {
24   HandleScope scope(isolate);
25   THROW_NEW_ERROR_RETURN_FAILURE(isolate,
26                                  NewError(MessageTemplate::kUnsupported));
27 }
28 
29 // -----------------------------------------------------------------------------
30 // Throwers for restricted function properties and strict arguments object
31 // properties
32 
BUILTIN(RestrictedFunctionPropertiesThrower)33 BUILTIN(RestrictedFunctionPropertiesThrower) {
34   HandleScope scope(isolate);
35   THROW_NEW_ERROR_RETURN_FAILURE(
36       isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
37 }
38 
BUILTIN(RestrictedStrictArgumentsPropertiesThrower)39 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
40   HandleScope scope(isolate);
41   THROW_NEW_ERROR_RETURN_FAILURE(
42       isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
43 }
44 
45 // -----------------------------------------------------------------------------
46 // Interrupt and stack checks.
47 
Generate_InterruptCheck(MacroAssembler * masm)48 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
49   masm->TailCallRuntime(Runtime::kInterrupt);
50 }
51 
Generate_StackCheck(MacroAssembler * masm)52 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
53   masm->TailCallRuntime(Runtime::kStackGuard);
54 }
55 
56 // -----------------------------------------------------------------------------
57 // TurboFan support builtins.
58 
Generate_CopyFastSmiOrObjectElements(compiler::CodeAssemblerState * state)59 void Builtins::Generate_CopyFastSmiOrObjectElements(
60     compiler::CodeAssemblerState* state) {
61   typedef CodeStubAssembler::Label Label;
62   typedef compiler::Node Node;
63   typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
64   CodeStubAssembler assembler(state);
65 
66   Node* object = assembler.Parameter(Descriptor::kObject);
67 
68   // Load the {object}s elements.
69   Node* source = assembler.LoadObjectField(object, JSObject::kElementsOffset);
70 
71   CodeStubAssembler::ParameterMode mode = assembler.OptimalParameterMode();
72   Node* length = assembler.TaggedToParameter(
73       assembler.LoadFixedArrayBaseLength(source), mode);
74 
75   // Check if we can allocate in new space.
76   ElementsKind kind = FAST_ELEMENTS;
77   int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
78   Label if_newspace(&assembler), if_oldspace(&assembler);
79   assembler.Branch(
80       assembler.UintPtrOrSmiLessThan(
81           length, assembler.IntPtrOrSmiConstant(max_elements, mode), mode),
82       &if_newspace, &if_oldspace);
83 
84   assembler.Bind(&if_newspace);
85   {
86     Node* target = assembler.AllocateFixedArray(kind, length, mode);
87     assembler.CopyFixedArrayElements(kind, source, target, length,
88                                      SKIP_WRITE_BARRIER, mode);
89     assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
90     assembler.Return(target);
91   }
92 
93   assembler.Bind(&if_oldspace);
94   {
95     Node* target = assembler.AllocateFixedArray(kind, length, mode,
96                                                 CodeStubAssembler::kPretenured);
97     assembler.CopyFixedArrayElements(kind, source, target, length,
98                                      UPDATE_WRITE_BARRIER, mode);
99     assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
100     assembler.Return(target);
101   }
102 }
103 
Generate_GrowFastDoubleElements(compiler::CodeAssemblerState * state)104 void Builtins::Generate_GrowFastDoubleElements(
105     compiler::CodeAssemblerState* state) {
106   typedef CodeStubAssembler::Label Label;
107   typedef compiler::Node Node;
108   typedef GrowArrayElementsDescriptor Descriptor;
109   CodeStubAssembler assembler(state);
110 
111   Node* object = assembler.Parameter(Descriptor::kObject);
112   Node* key = assembler.Parameter(Descriptor::kKey);
113   Node* context = assembler.Parameter(Descriptor::kContext);
114 
115   Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
116   Node* elements = assembler.LoadElements(object);
117   elements = assembler.TryGrowElementsCapacity(
118       object, elements, FAST_DOUBLE_ELEMENTS, key, &runtime);
119   assembler.Return(elements);
120 
121   assembler.Bind(&runtime);
122   assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
123 }
124 
Generate_GrowFastSmiOrObjectElements(compiler::CodeAssemblerState * state)125 void Builtins::Generate_GrowFastSmiOrObjectElements(
126     compiler::CodeAssemblerState* state) {
127   typedef CodeStubAssembler::Label Label;
128   typedef compiler::Node Node;
129   typedef GrowArrayElementsDescriptor Descriptor;
130   CodeStubAssembler assembler(state);
131 
132   Node* object = assembler.Parameter(Descriptor::kObject);
133   Node* key = assembler.Parameter(Descriptor::kKey);
134   Node* context = assembler.Parameter(Descriptor::kContext);
135 
136   Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
137   Node* elements = assembler.LoadElements(object);
138   elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS,
139                                                key, &runtime);
140   assembler.Return(elements);
141 
142   assembler.Bind(&runtime);
143   assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
144 }
145 
146 namespace {
147 
Generate_NewArgumentsElements(CodeStubAssembler * assembler,compiler::Node * frame,compiler::Node * length)148 void Generate_NewArgumentsElements(CodeStubAssembler* assembler,
149                                    compiler::Node* frame,
150                                    compiler::Node* length) {
151   typedef CodeStubAssembler::Label Label;
152   typedef CodeStubAssembler::Variable Variable;
153   typedef compiler::Node Node;
154 
155   // Check if we can allocate in new space.
156   ElementsKind kind = FAST_ELEMENTS;
157   int max_elements = FixedArray::GetMaxLengthForNewSpaceAllocation(kind);
158   Label if_newspace(assembler), if_oldspace(assembler, Label::kDeferred);
159   assembler->Branch(assembler->IntPtrLessThan(
160                         length, assembler->IntPtrConstant(max_elements)),
161                     &if_newspace, &if_oldspace);
162 
163   assembler->Bind(&if_newspace);
164   {
165     // Prefer EmptyFixedArray in case of non-positive {length} (the {length}
166     // can be negative here for rest parameters).
167     Label if_empty(assembler), if_notempty(assembler);
168     assembler->Branch(
169         assembler->IntPtrLessThanOrEqual(length, assembler->IntPtrConstant(0)),
170         &if_empty, &if_notempty);
171 
172     assembler->Bind(&if_empty);
173     assembler->Return(assembler->EmptyFixedArrayConstant());
174 
175     assembler->Bind(&if_notempty);
176     {
177       // Allocate a FixedArray in new space.
178       Node* result = assembler->AllocateFixedArray(kind, length);
179 
180       // Compute the effective {offset} into the {frame}.
181       Node* offset = assembler->IntPtrAdd(length, assembler->IntPtrConstant(1));
182 
183       // Copy the parameters from {frame} (starting at {offset}) to {result}.
184       Variable var_index(assembler, MachineType::PointerRepresentation());
185       Label loop(assembler, &var_index), done_loop(assembler);
186       var_index.Bind(assembler->IntPtrConstant(0));
187       assembler->Goto(&loop);
188       assembler->Bind(&loop);
189       {
190         // Load the current {index}.
191         Node* index = var_index.value();
192 
193         // Check if we are done.
194         assembler->GotoIf(assembler->WordEqual(index, length), &done_loop);
195 
196         // Load the parameter at the given {index}.
197         Node* value = assembler->Load(
198             MachineType::AnyTagged(), frame,
199             assembler->WordShl(assembler->IntPtrSub(offset, index),
200                                assembler->IntPtrConstant(kPointerSizeLog2)));
201 
202         // Store the {value} into the {result}.
203         assembler->StoreFixedArrayElement(result, index, value,
204                                           SKIP_WRITE_BARRIER);
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 
Generate_NewUnmappedArgumentsElements(compiler::CodeAssemblerState * state)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.GotoIfNot(assembler.MarkerIsFrameType(
253                           parent_frame_type, StackFrame::ARGUMENTS_ADAPTOR),
254                       &done);
255   {
256     // Determine the length from the ArgumentsAdaptorFrame.
257     Node* length = assembler.LoadAndUntagSmi(
258         parent_frame, ArgumentsAdaptorFrameConstants::kLengthOffset);
259 
260     // Take the arguments from the ArgumentsAdaptorFrame.
261     var_frame.Bind(parent_frame);
262     var_length.Bind(length);
263   }
264   assembler.Goto(&done);
265 
266   // Allocate the actual FixedArray for the elements.
267   assembler.Bind(&done);
268   Generate_NewArgumentsElements(&assembler, var_frame.value(),
269                                 var_length.value());
270 }
271 
Generate_NewRestParameterElements(compiler::CodeAssemblerState * state)272 void Builtins::Generate_NewRestParameterElements(
273     compiler::CodeAssemblerState* state) {
274   typedef CodeStubAssembler::Label Label;
275   typedef compiler::Node Node;
276   typedef NewArgumentsElementsDescriptor Descriptor;
277   CodeStubAssembler assembler(state);
278 
279   Node* formal_parameter_count =
280       assembler.Parameter(Descriptor::kFormalParameterCount);
281 
282   // Check if we have an ArgumentsAdaptorFrame, as we will only have rest
283   // parameters in that case.
284   Label if_empty(&assembler);
285   Node* frame = assembler.Load(
286       MachineType::Pointer(), assembler.LoadParentFramePointer(),
287       assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
288   Node* frame_type =
289       assembler.Load(MachineType::AnyTagged(), frame,
290                      assembler.IntPtrConstant(
291                          CommonFrameConstants::kContextOrFrameTypeOffset));
292   assembler.GotoIfNot(
293       assembler.MarkerIsFrameType(frame_type, StackFrame::ARGUMENTS_ADAPTOR),
294       &if_empty);
295 
296   // Determine the length from the ArgumentsAdaptorFrame.
297   Node* frame_length = assembler.LoadAndUntagSmi(
298       frame, ArgumentsAdaptorFrameConstants::kLengthOffset);
299 
300   // Compute the actual rest parameter length (may be negative).
301   Node* length = assembler.IntPtrSub(frame_length, formal_parameter_count);
302 
303   // Allocate the actual FixedArray for the elements.
304   Generate_NewArgumentsElements(&assembler, frame, length);
305 
306   // No rest parameters, return an empty FixedArray.
307   assembler.Bind(&if_empty);
308   assembler.Return(assembler.EmptyFixedArrayConstant());
309 }
310 
Generate_ReturnReceiver(compiler::CodeAssemblerState * state)311 void Builtins::Generate_ReturnReceiver(compiler::CodeAssemblerState* state) {
312   CodeStubAssembler assembler(state);
313   assembler.Return(assembler.Parameter(0));
314 }
315 
316 }  // namespace internal
317 }  // namespace v8
318