Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: src/x64/builtins-x64.cc

Issue 1468073004: Reshuffle registers in JSConstructStub to avoid trashing costructor and new.target on fast path (so… (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/codegen.h" 8 #include "src/codegen.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 { 132 {
133 FrameScope scope(masm, StackFrame::CONSTRUCT); 133 FrameScope scope(masm, StackFrame::CONSTRUCT);
134 134
135 // Preserve the incoming parameters on the stack. 135 // Preserve the incoming parameters on the stack.
136 __ AssertUndefinedOrAllocationSite(rbx); 136 __ AssertUndefinedOrAllocationSite(rbx);
137 __ Push(rbx); 137 __ Push(rbx);
138 __ Integer32ToSmi(rcx, rax); 138 __ Integer32ToSmi(rcx, rax);
139 __ Push(rcx); 139 __ Push(rcx);
140 140
141 if (create_implicit_receiver) { 141 if (create_implicit_receiver) {
142 __ Push(rdi);
143 __ Push(rdx);
144
145 // Try to allocate the object without transitioning into C code. If any of 142 // Try to allocate the object without transitioning into C code. If any of
146 // the preconditions is not met, the code bails out to the runtime call. 143 // the preconditions is not met, the code bails out to the runtime call.
147 Label rt_call, allocated; 144 Label rt_call, allocated;
148 if (FLAG_inline_new) { 145 if (FLAG_inline_new) {
149 // Verify that the new target is a JSFunction. 146 // Verify that the new target is a JSFunction.
150 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx); 147 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx);
151 __ j(not_equal, &rt_call); 148 __ j(not_equal, &rt_call);
152 149
153 // Load the initial map and verify that it is in fact a map. 150 // Load the initial map and verify that it is in fact a map.
154 // rdx: new target 151 // rdx: new target
(...skipping 21 matching lines...) Expand all
176 __ shrl(rsi, Immediate(Map::Counter::kShift)); 173 __ shrl(rsi, Immediate(Map::Counter::kShift));
177 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); 174 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
178 __ j(less, &allocate); 175 __ j(less, &allocate);
179 // Decrease generous allocation count. 176 // Decrease generous allocation count.
180 __ subl(FieldOperand(rax, Map::kBitField3Offset), 177 __ subl(FieldOperand(rax, Map::kBitField3Offset),
181 Immediate(1 << Map::Counter::kShift)); 178 Immediate(1 << Map::Counter::kShift));
182 179
183 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); 180 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
184 __ j(not_equal, &allocate); 181 __ j(not_equal, &allocate);
185 182
183 // Push the constructor, new_target and map to the stack, and
184 // the map again as an argument to the runtime call.
186 __ Push(rax); 185 __ Push(rax);
187 __ Push(rdx); 186 __ Push(rdx);
188 __ Push(rdi); 187 __ Push(rdi);
189 188
190 __ Push(rax); // initial map 189 __ Push(rax); // initial map
191 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 190 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
192 191
193 __ Pop(rdi); 192 __ Pop(rdi);
194 __ Pop(rdx); 193 __ Pop(rdx);
195 __ Pop(rax); 194 __ Pop(rax);
196 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); 195 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
197 196
198 __ bind(&allocate); 197 __ bind(&allocate);
199 } 198 }
200 199
201 // Now allocate the JSObject on the heap. 200 // Now allocate the JSObject on the heap.
202 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); 201 __ movzxbp(r9, FieldOperand(rax, Map::kInstanceSizeOffset));
203 __ shlp(rdi, Immediate(kPointerSizeLog2)); 202 __ shlp(r9, Immediate(kPointerSizeLog2));
204 // rdi: size of new object 203 // r9: size of new object
205 __ Allocate(rdi, rbx, rdi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 204 __ Allocate(r9, rbx, r9, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
206 // Allocated the JSObject, now initialize the fields. 205 // Allocated the JSObject, now initialize the fields.
206 // rdi: constructor
207 // rdx: new target
207 // rax: initial map 208 // rax: initial map
208 // rbx: JSObject (not HeapObject tagged - the actual address). 209 // rbx: JSObject (not HeapObject tagged - the actual address).
209 // rdi: start of next object 210 // r9: start of next object
210 __ movp(Operand(rbx, JSObject::kMapOffset), rax); 211 __ movp(Operand(rbx, JSObject::kMapOffset), rax);
211 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); 212 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
212 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); 213 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx);
213 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); 214 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx);
214 // Set extra fields in the newly allocated object. 215 // Set extra fields in the newly allocated object.
215 // rax: initial map 216 // rax: initial map
217 // rdx: new target
216 // rbx: JSObject 218 // rbx: JSObject
217 // rdi: start of next object 219 // r9: start of next object
218 // rsi: slack tracking counter (non-API function case) 220 // rsi: slack tracking counter (non-API function case)
219 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); 221 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize));
220 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 222 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex);
221 if (!is_api_function) { 223 if (!is_api_function) {
222 Label no_inobject_slack_tracking; 224 Label no_inobject_slack_tracking;
223 225
224 // Check if slack tracking is enabled. 226 // Check if slack tracking is enabled.
225 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); 227 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
226 __ j(less, &no_inobject_slack_tracking); 228 __ j(less, &no_inobject_slack_tracking);
227 229
228 // Allocate object with a slack. 230 // Allocate object with a slack.
229 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); 231 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
230 __ negp(rsi); 232 __ negp(rsi);
231 __ leap(rsi, Operand(rdi, rsi, times_pointer_size, 0)); 233 __ leap(rsi, Operand(r9, rsi, times_pointer_size, 0));
232 // rsi: offset of first field after pre-allocated fields 234 // rsi: offset of first field after pre-allocated fields
233 if (FLAG_debug_code) { 235 if (FLAG_debug_code) {
234 __ cmpp(rcx, rsi); 236 __ cmpp(rcx, rsi);
235 __ Assert(less_equal, 237 __ Assert(less_equal,
236 kUnexpectedNumberOfPreAllocatedPropertyFields); 238 kUnexpectedNumberOfPreAllocatedPropertyFields);
237 } 239 }
238 __ InitializeFieldsWithFiller(rcx, rsi, rdx); 240 __ InitializeFieldsWithFiller(rcx, rsi, r11);
239 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); 241
240 // Fill the remaining fields with one pointer filler map. 242 // To allow truncation fill the remaining fields with one pointer
243 // filler map.
244 __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex);
241 245
242 __ bind(&no_inobject_slack_tracking); 246 __ bind(&no_inobject_slack_tracking);
243 } 247 }
244 248
245 __ InitializeFieldsWithFiller(rcx, rdi, rdx); 249 __ InitializeFieldsWithFiller(rcx, r9, r11);
246 250
247 // Add the object tag to make the JSObject real, so that we can continue 251 // Add the object tag to make the JSObject real, so that we can continue
248 // and jump into the continuation code at any time from now on. 252 // and jump into the continuation code at any time from now on.
249 // rbx: JSObject (untagged) 253 // rbx: JSObject (untagged)
250 __ orp(rbx, Immediate(kHeapObjectTag)); 254 __ orp(rbx, Immediate(kHeapObjectTag));
251 255
252 // Continue with JSObject being successfully allocated 256 // Continue with JSObject being successfully allocated
257 // rdi: constructor
258 // rdx: new target
253 // rbx: JSObject (tagged) 259 // rbx: JSObject (tagged)
254 __ jmp(&allocated); 260 __ jmp(&allocated);
255 } 261 }
256 262
257 // Allocate the new receiver object using the runtime call. 263 // Allocate the new receiver object using the runtime call.
264 // rdi: constructor
258 // rdx: new target 265 // rdx: new target
259 __ bind(&rt_call); 266 __ bind(&rt_call);
260 int offset = kPointerSize;
261 267
262 // Must restore rsi (context) and rdi (constructor) before calling 268 // Must restore rsi (context) before calling runtime.
263 // runtime.
264 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 269 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
265 __ movp(rdi, Operand(rsp, offset)); 270
271 // Push the constructor and new_target twice, second pair as arguments
272 // to the runtime call.
273 __ Push(rdi);
274 __ Push(rdx);
266 __ Push(rdi); // constructor function 275 __ Push(rdi); // constructor function
267 __ Push(rdx); // new target 276 __ Push(rdx); // new target
268 __ CallRuntime(Runtime::kNewObject, 2); 277 __ CallRuntime(Runtime::kNewObject, 2);
269 __ movp(rbx, rax); // store result in rbx 278 __ movp(rbx, rax); // store result in rbx
279 __ Pop(rdx);
280 __ Pop(rdi);
270 281
271 // New object allocated. 282 // Receiver for constructor call allocated.
283 // rdi: constructor
284 // rdx: new target
272 // rbx: newly allocated object 285 // rbx: newly allocated object
273 __ bind(&allocated); 286 __ bind(&allocated);
274 287
275 // Restore the parameters.
276 __ Pop(rdx);
277 __ Pop(rdi);
278
279 // Retrieve smi-tagged arguments count from the stack. 288 // Retrieve smi-tagged arguments count from the stack.
280 __ movp(rax, Operand(rsp, 0)); 289 __ movp(rax, Operand(rsp, 0));
281 __ SmiToInteger32(rax, rax); 290 __ SmiToInteger32(rax, rax);
282 } 291 }
283 292
284 // Push new.target onto the construct frame. This is stored just below the 293 // Push new.target onto the construct frame. This is stored just below the
285 // receiver on the stack. 294 // receiver on the stack.
286 __ Push(rdx); 295 __ Push(rdx);
287 296
288 if (create_implicit_receiver) { 297 if (create_implicit_receiver) {
(...skipping 1621 matching lines...) Expand 10 before | Expand all | Expand 10 after
1910 __ ret(0); 1919 __ ret(0);
1911 } 1920 }
1912 1921
1913 1922
1914 #undef __ 1923 #undef __
1915 1924
1916 } // namespace internal 1925 } // namespace internal
1917 } // namespace v8 1926 } // namespace v8
1918 1927
1919 #endif // V8_TARGET_ARCH_X64 1928 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698