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

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

Issue 7891042: Add asserts to ensure that we: (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 3 months 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 | Annotate | Revision Log
« no previous file with comments | « src/frames.h ('k') | src/ia32/code-stubs-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 106 }
107 107
108 108
109 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 109 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
110 bool is_api_function, 110 bool is_api_function,
111 bool count_constructions) { 111 bool count_constructions) {
112 // Should never count constructions for api objects. 112 // Should never count constructions for api objects.
113 ASSERT(!is_api_function || !count_constructions); 113 ASSERT(!is_api_function || !count_constructions);
114 114
115 // Enter a construct frame. 115 // Enter a construct frame.
116 __ EnterConstructFrame(); 116 {
117 117 FrameScope scope(masm, StackFrame::CONSTRUCT);
118 // Store a smi-tagged arguments count on the stack. 118
119 __ SmiTag(eax); 119 // Store a smi-tagged arguments count on the stack.
120 __ push(eax); 120 __ SmiTag(eax);
121 121 __ push(eax);
122 // Push the function to invoke on the stack. 122
123 __ push(edi); 123 // Push the function to invoke on the stack.
124 124 __ push(edi);
125 // Try to allocate the object without transitioning into C code. If any of the 125
126 // preconditions is not met, the code bails out to the runtime call. 126 // Try to allocate the object without transitioning into C code. If any of
127 Label rt_call, allocated; 127 // the preconditions is not met, the code bails out to the runtime call.
128 if (FLAG_inline_new) { 128 Label rt_call, allocated;
129 Label undo_allocation; 129 if (FLAG_inline_new) {
130 Label undo_allocation;
130 #ifdef ENABLE_DEBUGGER_SUPPORT 131 #ifdef ENABLE_DEBUGGER_SUPPORT
131 ExternalReference debug_step_in_fp = 132 ExternalReference debug_step_in_fp =
132 ExternalReference::debug_step_in_fp_address(masm->isolate()); 133 ExternalReference::debug_step_in_fp_address(masm->isolate());
133 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); 134 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
134 __ j(not_equal, &rt_call); 135 __ j(not_equal, &rt_call);
135 #endif 136 #endif
136 137
137 // Verified that the constructor is a JSFunction. 138 // Verified that the constructor is a JSFunction.
138 // Load the initial map and verify that it is in fact a map. 139 // Load the initial map and verify that it is in fact a map.
139 // edi: constructor 140 // edi: constructor
140 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 141 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
141 // Will both indicate a NULL and a Smi 142 // Will both indicate a NULL and a Smi
142 __ JumpIfSmi(eax, &rt_call); 143 __ JumpIfSmi(eax, &rt_call);
143 // edi: constructor 144 // edi: constructor
144 // eax: initial map (if proven valid below) 145 // eax: initial map (if proven valid below)
145 __ CmpObjectType(eax, MAP_TYPE, ebx); 146 __ CmpObjectType(eax, MAP_TYPE, ebx);
146 __ j(not_equal, &rt_call); 147 __ j(not_equal, &rt_call);
147 148
148 // Check that the constructor is not constructing a JSFunction (see comments 149 // Check that the constructor is not constructing a JSFunction (see
149 // in Runtime_NewObject in runtime.cc). In which case the initial map's 150 // comments in Runtime_NewObject in runtime.cc). In which case the
150 // instance type would be JS_FUNCTION_TYPE. 151 // initial map's instance type would be JS_FUNCTION_TYPE.
151 // edi: constructor 152 // edi: constructor
152 // eax: initial map 153 // eax: initial map
153 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 154 __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
154 __ j(equal, &rt_call); 155 __ j(equal, &rt_call);
155 156
156 if (count_constructions) { 157 if (count_constructions) {
157 Label allocate; 158 Label allocate;
158 // Decrease generous allocation count. 159 // Decrease generous allocation count.
159 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 160 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
160 __ dec_b(FieldOperand(ecx, SharedFunctionInfo::kConstructionCountOffset)); 161 __ dec_b(FieldOperand(ecx,
161 __ j(not_zero, &allocate); 162 SharedFunctionInfo::kConstructionCountOffset));
162 163 __ j(not_zero, &allocate);
163 __ push(eax); 164
164 __ push(edi); 165 __ push(eax);
165 166 __ push(edi);
166 __ push(edi); // constructor 167
167 // The call will replace the stub, so the countdown is only done once. 168 __ push(edi); // constructor
168 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 169 // The call will replace the stub, so the countdown is only done once.
169 170 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
170 __ pop(edi); 171
171 __ pop(eax); 172 __ pop(edi);
172 173 __ pop(eax);
173 __ bind(&allocate); 174
175 __ bind(&allocate);
176 }
177
178 // Now allocate the JSObject on the heap.
179 // edi: constructor
180 // eax: initial map
181 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
182 __ shl(edi, kPointerSizeLog2);
183 __ AllocateInNewSpace(
184 edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
185 // Allocated the JSObject, now initialize the fields.
186 // eax: initial map
187 // ebx: JSObject
188 // edi: start of next object
189 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
190 Factory* factory = masm->isolate()->factory();
191 __ mov(ecx, factory->empty_fixed_array());
192 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
193 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
194 // Set extra fields in the newly allocated object.
195 // eax: initial map
196 // ebx: JSObject
197 // edi: start of next object
198 { Label loop, entry;
199 // To allow for truncation.
200 if (count_constructions) {
201 __ mov(edx, factory->one_pointer_filler_map());
202 } else {
203 __ mov(edx, factory->undefined_value());
204 }
205 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
206 __ jmp(&entry);
207 __ bind(&loop);
208 __ mov(Operand(ecx, 0), edx);
209 __ add(Operand(ecx), Immediate(kPointerSize));
210 __ bind(&entry);
211 __ cmp(ecx, Operand(edi));
212 __ j(less, &loop);
213 }
214
215 // Add the object tag to make the JSObject real, so that we can continue
216 // and jump into the continuation code at any time from now on. Any
217 // failures need to undo the allocation, so that the heap is in a
218 // consistent state and verifiable.
219 // eax: initial map
220 // ebx: JSObject
221 // edi: start of next object
222 __ or_(Operand(ebx), Immediate(kHeapObjectTag));
223
224 // Check if a non-empty properties array is needed.
225 // Allocate and initialize a FixedArray if it is.
226 // eax: initial map
227 // ebx: JSObject
228 // edi: start of next object
229 // Calculate the total number of properties described by the map.
230 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
231 __ movzx_b(ecx,
232 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
233 __ add(edx, Operand(ecx));
234 // Calculate unused properties past the end of the in-object properties.
235 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
236 __ sub(edx, Operand(ecx));
237 // Done if no extra properties are to be allocated.
238 __ j(zero, &allocated);
239 __ Assert(positive, "Property allocation count failed.");
240
241 // Scale the number of elements by pointer size and add the header for
242 // FixedArrays to the start of the next object calculation from above.
243 // ebx: JSObject
244 // edi: start of next object (will be start of FixedArray)
245 // edx: number of elements in properties array
246 __ AllocateInNewSpace(FixedArray::kHeaderSize,
247 times_pointer_size,
248 edx,
249 edi,
250 ecx,
251 no_reg,
252 &undo_allocation,
253 RESULT_CONTAINS_TOP);
254
255 // Initialize the FixedArray.
256 // ebx: JSObject
257 // edi: FixedArray
258 // edx: number of elements
259 // ecx: start of next object
260 __ mov(eax, factory->fixed_array_map());
261 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
262 __ SmiTag(edx);
263 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
264
265 // Initialize the fields to undefined.
266 // ebx: JSObject
267 // edi: FixedArray
268 // ecx: start of next object
269 { Label loop, entry;
270 __ mov(edx, factory->undefined_value());
271 __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
272 __ jmp(&entry);
273 __ bind(&loop);
274 __ mov(Operand(eax, 0), edx);
275 __ add(Operand(eax), Immediate(kPointerSize));
276 __ bind(&entry);
277 __ cmp(eax, Operand(ecx));
278 __ j(below, &loop);
279 }
280
281 // Store the initialized FixedArray into the properties field of
282 // the JSObject
283 // ebx: JSObject
284 // edi: FixedArray
285 __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag
286 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
287
288
289 // Continue with JSObject being successfully allocated
290 // ebx: JSObject
291 __ jmp(&allocated);
292
293 // Undo the setting of the new top so that the heap is verifiable. For
294 // example, the map's unused properties potentially do not match the
295 // allocated objects unused properties.
296 // ebx: JSObject (previous new top)
297 __ bind(&undo_allocation);
298 __ UndoAllocationInNewSpace(ebx);
174 } 299 }
175 300
176 // Now allocate the JSObject on the heap. 301 // Allocate the new receiver object using the runtime call.
177 // edi: constructor 302 __ bind(&rt_call);
178 // eax: initial map 303 // Must restore edi (constructor) before calling runtime.
179 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 304 __ mov(edi, Operand(esp, 0));
180 __ shl(edi, kPointerSizeLog2); 305 // edi: function (constructor)
181 __ AllocateInNewSpace(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 306 __ push(edi);
182 // Allocated the JSObject, now initialize the fields. 307 __ CallRuntime(Runtime::kNewObject, 1);
183 // eax: initial map 308 __ mov(ebx, Operand(eax)); // store result in ebx
184 // ebx: JSObject 309
185 // edi: start of next object 310 // New object allocated.
186 __ mov(Operand(ebx, JSObject::kMapOffset), eax); 311 // ebx: newly allocated object
187 Factory* factory = masm->isolate()->factory(); 312 __ bind(&allocated);
188 __ mov(ecx, factory->empty_fixed_array()); 313 // Retrieve the function from the stack.
189 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 314 __ pop(edi);
190 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 315
191 // Set extra fields in the newly allocated object. 316 // Retrieve smi-tagged arguments count from the stack.
192 // eax: initial map 317 __ mov(eax, Operand(esp, 0));
193 // ebx: JSObject 318 __ SmiUntag(eax);
194 // edi: start of next object 319
195 { Label loop, entry; 320 // Push the allocated receiver to the stack. We need two copies
196 // To allow for truncation. 321 // because we may have to return the original one and the calling
197 if (count_constructions) { 322 // conventions dictate that the called function pops the receiver.
198 __ mov(edx, factory->one_pointer_filler_map()); 323 __ push(ebx);
199 } else { 324 __ push(ebx);
200 __ mov(edx, factory->undefined_value()); 325
201 } 326 // Setup pointer to last argument.
202 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 327 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
203 __ jmp(&entry); 328
204 __ bind(&loop); 329 // Copy arguments and receiver to the expression stack.
205 __ mov(Operand(ecx, 0), edx); 330 Label loop, entry;
206 __ add(Operand(ecx), Immediate(kPointerSize)); 331 __ mov(ecx, Operand(eax));
207 __ bind(&entry); 332 __ jmp(&entry);
208 __ cmp(ecx, Operand(edi)); 333 __ bind(&loop);
209 __ j(less, &loop); 334 __ push(Operand(ebx, ecx, times_4, 0));
335 __ bind(&entry);
336 __ dec(ecx);
337 __ j(greater_equal, &loop);
338
339 // Call the function.
340 if (is_api_function) {
341 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
342 Handle<Code> code =
343 masm->isolate()->builtins()->HandleApiCallConstruct();
344 ParameterCount expected(0);
345 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
346 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
347 } else {
348 ParameterCount actual(eax);
349 __ InvokeFunction(edi, actual, CALL_FUNCTION,
350 NullCallWrapper(), CALL_AS_METHOD);
210 } 351 }
211 352
212 // Add the object tag to make the JSObject real, so that we can continue and 353 // Restore context from the frame.
213 // jump into the continuation code at any time from now on. Any failures 354 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
214 // need to undo the allocation, so that the heap is in a consistent state 355
215 // and verifiable. 356 // If the result is an object (in the ECMA sense), we should get rid
216 // eax: initial map 357 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
217 // ebx: JSObject 358 // on page 74.
218 // edi: start of next object 359 Label use_receiver, exit;
219 __ or_(Operand(ebx), Immediate(kHeapObjectTag)); 360
220 361 // If the result is a smi, it is *not* an object in the ECMA sense.
221 // Check if a non-empty properties array is needed. 362 __ JumpIfSmi(eax, &use_receiver);
222 // Allocate and initialize a FixedArray if it is. 363
223 // eax: initial map 364 // If the type of the result (stored in its map) is less than
224 // ebx: JSObject 365 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
225 // edi: start of next object 366 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
226 // Calculate the total number of properties described by the map. 367 __ j(above_equal, &exit);
227 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); 368
228 __ movzx_b(ecx, FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 369 // Throw away the result of the constructor invocation and use the
229 __ add(edx, Operand(ecx)); 370 // on-stack receiver as the result.
230 // Calculate unused properties past the end of the in-object properties. 371 __ bind(&use_receiver);
231 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset)); 372 __ mov(eax, Operand(esp, 0));
232 __ sub(edx, Operand(ecx)); 373
233 // Done if no extra properties are to be allocated. 374 // Restore the arguments count and leave the construct frame.
234 __ j(zero, &allocated); 375 __ bind(&exit);
235 __ Assert(positive, "Property allocation count failed."); 376 __ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count.
236 377
237 // Scale the number of elements by pointer size and add the header for 378 // Leave construct frame.
238 // FixedArrays to the start of the next object calculation from above.
239 // ebx: JSObject
240 // edi: start of next object (will be start of FixedArray)
241 // edx: number of elements in properties array
242 __ AllocateInNewSpace(FixedArray::kHeaderSize,
243 times_pointer_size,
244 edx,
245 edi,
246 ecx,
247 no_reg,
248 &undo_allocation,
249 RESULT_CONTAINS_TOP);
250
251 // Initialize the FixedArray.
252 // ebx: JSObject
253 // edi: FixedArray
254 // edx: number of elements
255 // ecx: start of next object
256 __ mov(eax, factory->fixed_array_map());
257 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
258 __ SmiTag(edx);
259 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
260
261 // Initialize the fields to undefined.
262 // ebx: JSObject
263 // edi: FixedArray
264 // ecx: start of next object
265 { Label loop, entry;
266 __ mov(edx, factory->undefined_value());
267 __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
268 __ jmp(&entry);
269 __ bind(&loop);
270 __ mov(Operand(eax, 0), edx);
271 __ add(Operand(eax), Immediate(kPointerSize));
272 __ bind(&entry);
273 __ cmp(eax, Operand(ecx));
274 __ j(below, &loop);
275 }
276
277 // Store the initialized FixedArray into the properties field of
278 // the JSObject
279 // ebx: JSObject
280 // edi: FixedArray
281 __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag
282 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
283
284
285 // Continue with JSObject being successfully allocated
286 // ebx: JSObject
287 __ jmp(&allocated);
288
289 // Undo the setting of the new top so that the heap is verifiable. For
290 // example, the map's unused properties potentially do not match the
291 // allocated objects unused properties.
292 // ebx: JSObject (previous new top)
293 __ bind(&undo_allocation);
294 __ UndoAllocationInNewSpace(ebx);
295 } 379 }
296 380
297 // Allocate the new receiver object using the runtime call.
298 __ bind(&rt_call);
299 // Must restore edi (constructor) before calling runtime.
300 __ mov(edi, Operand(esp, 0));
301 // edi: function (constructor)
302 __ push(edi);
303 __ CallRuntime(Runtime::kNewObject, 1);
304 __ mov(ebx, Operand(eax)); // store result in ebx
305
306 // New object allocated.
307 // ebx: newly allocated object
308 __ bind(&allocated);
309 // Retrieve the function from the stack.
310 __ pop(edi);
311
312 // Retrieve smi-tagged arguments count from the stack.
313 __ mov(eax, Operand(esp, 0));
314 __ SmiUntag(eax);
315
316 // Push the allocated receiver to the stack. We need two copies
317 // because we may have to return the original one and the calling
318 // conventions dictate that the called function pops the receiver.
319 __ push(ebx);
320 __ push(ebx);
321
322 // Setup pointer to last argument.
323 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
324
325 // Copy arguments and receiver to the expression stack.
326 Label loop, entry;
327 __ mov(ecx, Operand(eax));
328 __ jmp(&entry);
329 __ bind(&loop);
330 __ push(Operand(ebx, ecx, times_4, 0));
331 __ bind(&entry);
332 __ dec(ecx);
333 __ j(greater_equal, &loop);
334
335 // Call the function.
336 if (is_api_function) {
337 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
338 Handle<Code> code =
339 masm->isolate()->builtins()->HandleApiCallConstruct();
340 ParameterCount expected(0);
341 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
342 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
343 } else {
344 ParameterCount actual(eax);
345 __ InvokeFunction(edi, actual, CALL_FUNCTION,
346 NullCallWrapper(), CALL_AS_METHOD);
347 }
348
349 // Restore context from the frame.
350 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
351
352 // If the result is an object (in the ECMA sense), we should get rid
353 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
354 // on page 74.
355 Label use_receiver, exit;
356
357 // If the result is a smi, it is *not* an object in the ECMA sense.
358 __ JumpIfSmi(eax, &use_receiver);
359
360 // If the type of the result (stored in its map) is less than
361 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
362 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
363 __ j(above_equal, &exit);
364
365 // Throw away the result of the constructor invocation and use the
366 // on-stack receiver as the result.
367 __ bind(&use_receiver);
368 __ mov(eax, Operand(esp, 0));
369
370 // Restore the arguments count and leave the construct frame.
371 __ bind(&exit);
372 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count
373 __ LeaveConstructFrame();
374
375 // Remove caller arguments from the stack and return. 381 // Remove caller arguments from the stack and return.
376 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 382 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
377 __ pop(ecx); 383 __ pop(ecx);
378 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 384 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
379 __ push(ecx); 385 __ push(ecx);
380 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 386 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
381 __ ret(0); 387 __ ret(0);
382 } 388 }
383 389
384 390
385 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 391 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
386 Generate_JSConstructStubHelper(masm, false, true); 392 Generate_JSConstructStubHelper(masm, false, true);
387 } 393 }
388 394
389 395
390 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 396 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
391 Generate_JSConstructStubHelper(masm, false, false); 397 Generate_JSConstructStubHelper(masm, false, false);
392 } 398 }
393 399
394 400
395 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 401 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
396 Generate_JSConstructStubHelper(masm, true, false); 402 Generate_JSConstructStubHelper(masm, true, false);
397 } 403 }
398 404
399 405
400 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 406 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
401 bool is_construct) { 407 bool is_construct) {
402 // Clear the context before we push it when entering the JS frame. 408 // Clear the context before we push it when entering the internal frame.
403 __ Set(esi, Immediate(0)); 409 __ Set(esi, Immediate(0));
404 410
405 // Enter an internal frame. 411 {
406 __ EnterInternalFrame(); 412 FrameScope scope(masm, StackFrame::INTERNAL);
407 413
408 // Load the previous frame pointer (ebx) to access C arguments 414 // Load the previous frame pointer (ebx) to access C arguments
409 __ mov(ebx, Operand(ebp, 0)); 415 __ mov(ebx, Operand(ebp, 0));
410 416
411 // Get the function from the frame and setup the context. 417 // Get the function from the frame and setup the context.
412 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 418 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
413 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); 419 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));
414 420
415 // Push the function and the receiver onto the stack. 421 // Push the function and the receiver onto the stack.
416 __ push(ecx); 422 __ push(ecx);
417 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 423 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
418 424
419 // Load the number of arguments and setup pointer to the arguments. 425 // Load the number of arguments and setup pointer to the arguments.
420 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 426 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
421 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 427 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
422 428
423 // Copy arguments to the stack in a loop. 429 // Copy arguments to the stack in a loop.
424 Label loop, entry; 430 Label loop, entry;
425 __ Set(ecx, Immediate(0)); 431 __ Set(ecx, Immediate(0));
426 __ jmp(&entry); 432 __ jmp(&entry);
427 __ bind(&loop); 433 __ bind(&loop);
428 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 434 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv
429 __ push(Operand(edx, 0)); // dereference handle 435 __ push(Operand(edx, 0)); // dereference handle
430 __ inc(Operand(ecx)); 436 __ inc(Operand(ecx));
431 __ bind(&entry); 437 __ bind(&entry);
432 __ cmp(ecx, Operand(eax)); 438 __ cmp(ecx, Operand(eax));
433 __ j(not_equal, &loop); 439 __ j(not_equal, &loop);
434 440
435 // Get the function from the stack and call it. 441 // Get the function from the stack and call it.
436 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver 442 // kPointerSize for the receiver.
443 __ mov(edi, Operand(esp, eax, times_4, kPointerSize));
437 444
438 // Invoke the code. 445 // Invoke the code.
439 if (is_construct) { 446 if (is_construct) {
440 __ call(masm->isolate()->builtins()->JSConstructCall(), 447 __ call(masm->isolate()->builtins()->JSConstructCall(),
441 RelocInfo::CODE_TARGET); 448 RelocInfo::CODE_TARGET);
442 } else { 449 } else {
443 ParameterCount actual(eax); 450 ParameterCount actual(eax);
444 __ InvokeFunction(edi, actual, CALL_FUNCTION, 451 __ InvokeFunction(edi, actual, CALL_FUNCTION,
445 NullCallWrapper(), CALL_AS_METHOD); 452 NullCallWrapper(), CALL_AS_METHOD);
453 }
454
455 // Exit the internal frame. Notice that this also removes the empty.
456 // context and the function left on the stack by the code
457 // invocation.
446 } 458 }
447 459 __ ret(kPointerSize); // Remove receiver.
448 // Exit the JS frame. Notice that this also removes the empty
449 // context and the function left on the stack by the code
450 // invocation.
451 __ LeaveInternalFrame();
452 __ ret(1 * kPointerSize); // remove receiver
453 } 460 }
454 461
455 462
456 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 463 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
457 Generate_JSEntryTrampolineHelper(masm, false); 464 Generate_JSEntryTrampolineHelper(masm, false);
458 } 465 }
459 466
460 467
461 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 468 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
462 Generate_JSEntryTrampolineHelper(masm, true); 469 Generate_JSEntryTrampolineHelper(masm, true);
463 } 470 }
464 471
465 472
466 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { 473 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
467 // Enter an internal frame. 474 {
468 __ EnterInternalFrame(); 475 FrameScope scope(masm, StackFrame::INTERNAL);
469 476
470 // Push a copy of the function. 477 // Push a copy of the function.
471 __ push(edi); 478 __ push(edi);
472 // Push call kind information. 479 // Push call kind information.
473 __ push(ecx); 480 __ push(ecx);
474 481
475 __ push(edi); // Function is also the parameter to the runtime call. 482 __ push(edi); // Function is also the parameter to the runtime call.
476 __ CallRuntime(Runtime::kLazyCompile, 1); 483 __ CallRuntime(Runtime::kLazyCompile, 1);
477 484
478 // Restore call kind information. 485 // Restore call kind information.
479 __ pop(ecx); 486 __ pop(ecx);
480 // Restore receiver. 487 // Restore receiver.
481 __ pop(edi); 488 __ pop(edi);
482 489
483 // Tear down temporary frame. 490 // Tear down internal frame.
484 __ LeaveInternalFrame(); 491 }
485 492
486 // Do a tail-call of the compiled function. 493 // Do a tail-call of the compiled function.
487 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 494 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
488 __ jmp(Operand(eax)); 495 __ jmp(Operand(eax));
489 } 496 }
490 497
491 498
492 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 499 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
493 // Enter an internal frame. 500 {
494 __ EnterInternalFrame(); 501 FrameScope scope(masm, StackFrame::INTERNAL);
495 502
496 // Push a copy of the function onto the stack. 503 // Push a copy of the function onto the stack.
497 __ push(edi); 504 __ push(edi);
498 // Push call kind information. 505 // Push call kind information.
499 __ push(ecx); 506 __ push(ecx);
500 507
501 __ push(edi); // Function is also the parameter to the runtime call. 508 __ push(edi); // Function is also the parameter to the runtime call.
502 __ CallRuntime(Runtime::kLazyRecompile, 1); 509 __ CallRuntime(Runtime::kLazyRecompile, 1);
503 510
504 // Restore call kind information. 511 // Restore call kind information.
505 __ pop(ecx); 512 __ pop(ecx);
506 // Restore receiver. 513 // Restore receiver.
507 __ pop(edi); 514 __ pop(edi);
508 515
509 // Tear down temporary frame. 516 // Tear down internal frame.
510 __ LeaveInternalFrame(); 517 }
511 518
512 // Do a tail-call of the compiled function. 519 // Do a tail-call of the compiled function.
513 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 520 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
514 __ jmp(Operand(eax)); 521 __ jmp(Operand(eax));
515 } 522 }
516 523
517 524
518 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 525 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
519 Deoptimizer::BailoutType type) { 526 Deoptimizer::BailoutType type) {
520 // Enter an internal frame. 527 {
521 __ EnterInternalFrame(); 528 FrameScope scope(masm, StackFrame::INTERNAL);
522 529
523 // Pass the function and deoptimization type to the runtime system. 530 // Pass the function and deoptimization type to the runtime system.
524 __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 531 __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
525 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 532 __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
526 533
527 // Tear down temporary frame. 534 // Tear down internal frame.
528 __ LeaveInternalFrame(); 535 }
529 536
530 // Get the full codegen state from the stack and untag it. 537 // Get the full codegen state from the stack and untag it.
531 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 538 __ mov(ecx, Operand(esp, 1 * kPointerSize));
532 __ SmiUntag(ecx); 539 __ SmiUntag(ecx);
533 540
534 // Switch on the state. 541 // Switch on the state.
535 Label not_no_registers, not_tos_eax; 542 Label not_no_registers, not_tos_eax;
536 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); 543 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
537 __ j(not_equal, &not_no_registers, Label::kNear); 544 __ j(not_equal, &not_no_registers, Label::kNear);
538 __ ret(1 * kPointerSize); // Remove state. 545 __ ret(1 * kPointerSize); // Remove state.
(...skipping 20 matching lines...) Expand all
559 566
560 567
561 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { 568 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
562 // TODO(kasperl): Do we need to save/restore the XMM registers too? 569 // TODO(kasperl): Do we need to save/restore the XMM registers too?
563 570
564 // For now, we are relying on the fact that Runtime::NotifyOSR 571 // For now, we are relying on the fact that Runtime::NotifyOSR
565 // doesn't do any garbage collection which allows us to save/restore 572 // doesn't do any garbage collection which allows us to save/restore
566 // the registers without worrying about which of them contain 573 // the registers without worrying about which of them contain
567 // pointers. This seems a bit fragile. 574 // pointers. This seems a bit fragile.
568 __ pushad(); 575 __ pushad();
569 __ EnterInternalFrame(); 576 {
570 __ CallRuntime(Runtime::kNotifyOSR, 0); 577 FrameScope scope(masm, StackFrame::INTERNAL);
571 __ LeaveInternalFrame(); 578 __ CallRuntime(Runtime::kNotifyOSR, 0);
579 }
572 __ popad(); 580 __ popad();
573 __ ret(0); 581 __ ret(0);
574 } 582 }
575 583
576 584
577 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 585 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
578 Factory* factory = masm->isolate()->factory(); 586 Factory* factory = masm->isolate()->factory();
579 587
580 // 1. Make sure we have at least one argument. 588 // 1. Make sure we have at least one argument.
581 { Label done; 589 { Label done;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 __ JumpIfSmi(ebx, &convert_to_object); 632 __ JumpIfSmi(ebx, &convert_to_object);
625 __ cmp(ebx, factory->null_value()); 633 __ cmp(ebx, factory->null_value());
626 __ j(equal, &use_global_receiver); 634 __ j(equal, &use_global_receiver);
627 __ cmp(ebx, factory->undefined_value()); 635 __ cmp(ebx, factory->undefined_value());
628 __ j(equal, &use_global_receiver); 636 __ j(equal, &use_global_receiver);
629 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 637 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
630 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 638 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
631 __ j(above_equal, &shift_arguments); 639 __ j(above_equal, &shift_arguments);
632 640
633 __ bind(&convert_to_object); 641 __ bind(&convert_to_object);
634 __ EnterInternalFrame(); // In order to preserve argument count.
635 __ SmiTag(eax);
636 __ push(eax);
637 642
638 __ push(ebx); 643 { // In order to preserve argument count.
639 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 644 FrameScope scope(masm, StackFrame::INTERNAL);
640 __ mov(ebx, eax); 645 __ SmiTag(eax);
641 __ Set(edx, Immediate(0)); // restore 646 __ push(eax);
642 647
643 __ pop(eax); 648 __ push(ebx);
644 __ SmiUntag(eax); 649 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
645 __ LeaveInternalFrame(); 650 __ mov(ebx, eax);
651 __ Set(edx, Immediate(0)); // restore
652
653 __ pop(eax);
654 __ SmiUntag(eax);
655 }
656
646 // Restore the function to edi. 657 // Restore the function to edi.
647 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 658 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
648 __ jmp(&patch_receiver); 659 __ jmp(&patch_receiver);
649 660
650 // Use the global receiver object from the called function as the 661 // Use the global receiver object from the called function as the
651 // receiver. 662 // receiver.
652 __ bind(&use_global_receiver); 663 __ bind(&use_global_receiver);
653 const int kGlobalIndex = 664 const int kGlobalIndex =
654 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 665 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
655 __ mov(ebx, FieldOperand(esi, kGlobalIndex)); 666 __ mov(ebx, FieldOperand(esi, kGlobalIndex));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 ParameterCount expected(0); 744 ParameterCount expected(0);
734 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION, 745 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION,
735 NullCallWrapper(), CALL_AS_METHOD); 746 NullCallWrapper(), CALL_AS_METHOD);
736 } 747 }
737 748
738 749
739 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 750 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
740 static const int kArgumentsOffset = 2 * kPointerSize; 751 static const int kArgumentsOffset = 2 * kPointerSize;
741 static const int kReceiverOffset = 3 * kPointerSize; 752 static const int kReceiverOffset = 3 * kPointerSize;
742 static const int kFunctionOffset = 4 * kPointerSize; 753 static const int kFunctionOffset = 4 * kPointerSize;
743 754 {
744 __ EnterInternalFrame(); 755 FrameScope frame_scope(masm, StackFrame::INTERNAL);
745 756
746 __ push(Operand(ebp, kFunctionOffset)); // push this 757 __ push(Operand(ebp, kFunctionOffset)); // push this
747 __ push(Operand(ebp, kArgumentsOffset)); // push arguments 758 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
748 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 759 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
749 760
750 // Check the stack for overflow. We are not trying to catch 761 // Check the stack for overflow. We are not trying to catch
751 // interruptions (e.g. debug break and preemption) here, so the "real stack 762 // interruptions (e.g. debug break and preemption) here, so the "real stack
752 // limit" is checked. 763 // limit" is checked.
753 Label okay; 764 Label okay;
754 ExternalReference real_stack_limit = 765 ExternalReference real_stack_limit =
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 // Invoke the function. 879 // Invoke the function.
869 Label call_proxy; 880 Label call_proxy;
870 ParameterCount actual(eax); 881 ParameterCount actual(eax);
871 __ SmiUntag(eax); 882 __ SmiUntag(eax);
872 __ mov(edi, Operand(ebp, kFunctionOffset)); 883 __ mov(edi, Operand(ebp, kFunctionOffset));
873 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 884 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
874 __ j(not_equal, &call_proxy); 885 __ j(not_equal, &call_proxy);
875 __ InvokeFunction(edi, actual, CALL_FUNCTION, 886 __ InvokeFunction(edi, actual, CALL_FUNCTION,
876 NullCallWrapper(), CALL_AS_METHOD); 887 NullCallWrapper(), CALL_AS_METHOD);
877 888
878 __ LeaveInternalFrame(); 889 frame_scope.GenerateLeaveFrame();
879 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 890 __ ret(3 * kPointerSize); // remove this, receiver, and arguments
880 891
881 // Invoke the function proxy. 892 // Invoke the function proxy.
882 __ bind(&call_proxy); 893 __ bind(&call_proxy);
883 __ push(edi); // add function proxy as last argument 894 __ push(edi); // add function proxy as last argument
884 __ inc(eax); 895 __ inc(eax);
885 __ Set(ebx, Immediate(0)); 896 __ Set(ebx, Immediate(0));
886 __ SetCallKind(ecx, CALL_AS_METHOD); 897 __ SetCallKind(ecx, CALL_AS_METHOD);
887 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 898 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
888 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 899 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
889 RelocInfo::CODE_TARGET); 900 RelocInfo::CODE_TARGET);
890 901
891 __ LeaveInternalFrame(); 902 // Leave internal frame.
903 }
892 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 904 __ ret(3 * kPointerSize); // remove this, receiver, and arguments
893 } 905 }
894 906
895 907
896 // Number of empty elements to allocate for an empty array. 908 // Number of empty elements to allocate for an empty array.
897 static const int kPreallocatedArrayElements = 4; 909 static const int kPreallocatedArrayElements = 4;
898 910
899 911
900 // Allocate an empty JSArray. The allocated array is put into the result 912 // Allocate an empty JSArray. The allocated array is put into the result
901 // register. If the parameter initial_capacity is larger than zero an elements 913 // register. If the parameter initial_capacity is larger than zero an elements
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1432 __ JumpIfSmi(eax, &convert_argument); 1444 __ JumpIfSmi(eax, &convert_argument);
1433 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); 1445 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
1434 __ j(NegateCondition(is_string), &convert_argument); 1446 __ j(NegateCondition(is_string), &convert_argument);
1435 __ mov(ebx, eax); 1447 __ mov(ebx, eax);
1436 __ IncrementCounter(counters->string_ctor_string_value(), 1); 1448 __ IncrementCounter(counters->string_ctor_string_value(), 1);
1437 __ jmp(&argument_is_string); 1449 __ jmp(&argument_is_string);
1438 1450
1439 // Invoke the conversion builtin and put the result into ebx. 1451 // Invoke the conversion builtin and put the result into ebx.
1440 __ bind(&convert_argument); 1452 __ bind(&convert_argument);
1441 __ IncrementCounter(counters->string_ctor_conversions(), 1); 1453 __ IncrementCounter(counters->string_ctor_conversions(), 1);
1442 __ EnterInternalFrame(); 1454 {
1443 __ push(edi); // Preserve the function. 1455 FrameScope scope(masm, StackFrame::INTERNAL);
1444 __ push(eax); 1456 __ push(edi); // Preserve the function.
1445 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 1457 __ push(eax);
1446 __ pop(edi); 1458 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1447 __ LeaveInternalFrame(); 1459 __ pop(edi);
1460 }
1448 __ mov(ebx, eax); 1461 __ mov(ebx, eax);
1449 __ jmp(&argument_is_string); 1462 __ jmp(&argument_is_string);
1450 1463
1451 // Load the empty string into ebx, remove the receiver from the 1464 // Load the empty string into ebx, remove the receiver from the
1452 // stack, and jump back to the case where the argument is a string. 1465 // stack, and jump back to the case where the argument is a string.
1453 __ bind(&no_arguments); 1466 __ bind(&no_arguments);
1454 __ Set(ebx, Immediate(factory->empty_string())); 1467 __ Set(ebx, Immediate(factory->empty_string()));
1455 __ pop(ecx); 1468 __ pop(ecx);
1456 __ lea(esp, Operand(esp, kPointerSize)); 1469 __ lea(esp, Operand(esp, kPointerSize));
1457 __ push(ecx); 1470 __ push(ecx);
1458 __ jmp(&argument_is_string); 1471 __ jmp(&argument_is_string);
1459 1472
1460 // At this point the argument is already a string. Call runtime to 1473 // At this point the argument is already a string. Call runtime to
1461 // create a string wrapper. 1474 // create a string wrapper.
1462 __ bind(&gc_required); 1475 __ bind(&gc_required);
1463 __ IncrementCounter(counters->string_ctor_gc_required(), 1); 1476 __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1464 __ EnterInternalFrame(); 1477 {
1465 __ push(ebx); 1478 FrameScope scope(masm, StackFrame::INTERNAL);
1466 __ CallRuntime(Runtime::kNewStringWrapper, 1); 1479 __ push(ebx);
1467 __ LeaveInternalFrame(); 1480 __ CallRuntime(Runtime::kNewStringWrapper, 1);
1481 }
1468 __ ret(0); 1482 __ ret(0);
1469 } 1483 }
1470 1484
1471 1485
1472 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1486 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1473 __ push(ebp); 1487 __ push(ebp);
1474 __ mov(ebp, Operand(esp)); 1488 __ mov(ebp, Operand(esp));
1475 1489
1476 // Store the arguments adaptor context sentinel. 1490 // Store the arguments adaptor context sentinel.
1477 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1491 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 // ------------------------------------------- 1596 // -------------------------------------------
1583 // Dont adapt arguments. 1597 // Dont adapt arguments.
1584 // ------------------------------------------- 1598 // -------------------------------------------
1585 __ bind(&dont_adapt_arguments); 1599 __ bind(&dont_adapt_arguments);
1586 __ jmp(Operand(edx)); 1600 __ jmp(Operand(edx));
1587 } 1601 }
1588 1602
1589 1603
1590 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1604 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1591 CpuFeatures::TryForceFeatureScope scope(SSE2); 1605 CpuFeatures::TryForceFeatureScope scope(SSE2);
1592 if (!CpuFeatures::IsSupported(SSE2)) { 1606 if (!CpuFeatures::IsSupported(SSE2) && FLAG_debug_code) {
1593 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); 1607 __ Abort("Unreachable code: Cannot optimize without SSE2 support.");
1594 return; 1608 return;
1595 } 1609 }
1596 1610
1597 // Get the loop depth of the stack guard check. This is recorded in 1611 // Get the loop depth of the stack guard check. This is recorded in
1598 // a test(eax, depth) instruction right after the call. 1612 // a test(eax, depth) instruction right after the call.
1599 Label stack_check; 1613 Label stack_check;
1600 __ mov(ebx, Operand(esp, 0)); // return address 1614 __ mov(ebx, Operand(esp, 0)); // return address
1601 if (FLAG_debug_code) { 1615 if (FLAG_debug_code) {
1602 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte); 1616 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte);
1603 __ Assert(equal, "test eax instruction not found after loop stack check"); 1617 __ Assert(equal, "test eax instruction not found after loop stack check");
1604 } 1618 }
1605 __ movzx_b(ebx, Operand(ebx, 1)); // depth 1619 __ movzx_b(ebx, Operand(ebx, 1)); // depth
1606 1620
1607 // Get the loop nesting level at which we allow OSR from the 1621 // Get the loop nesting level at which we allow OSR from the
1608 // unoptimized code and check if we want to do OSR yet. If not we 1622 // unoptimized code and check if we want to do OSR yet. If not we
1609 // should perform a stack guard check so we can get interrupts while 1623 // should perform a stack guard check so we can get interrupts while
1610 // waiting for on-stack replacement. 1624 // waiting for on-stack replacement.
1611 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1625 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1612 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 1626 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
1613 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); 1627 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset));
1614 __ cmpb(ebx, FieldOperand(ecx, Code::kAllowOSRAtLoopNestingLevelOffset)); 1628 __ cmpb(ebx, FieldOperand(ecx, Code::kAllowOSRAtLoopNestingLevelOffset));
1615 __ j(greater, &stack_check); 1629 __ j(greater, &stack_check);
1616 1630
1617 // Pass the function to optimize as the argument to the on-stack 1631 // Pass the function to optimize as the argument to the on-stack
1618 // replacement runtime function. 1632 // replacement runtime function.
1619 __ EnterInternalFrame(); 1633 {
1620 __ push(eax); 1634 FrameScope scope(masm, StackFrame::INTERNAL);
1621 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1635 __ push(eax);
1622 __ LeaveInternalFrame(); 1636 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1637 }
1623 1638
1624 // If the result was -1 it means that we couldn't optimize the 1639 // If the result was -1 it means that we couldn't optimize the
1625 // function. Just return and continue in the unoptimized version. 1640 // function. Just return and continue in the unoptimized version.
1626 Label skip; 1641 Label skip;
1627 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); 1642 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1)));
1628 __ j(not_equal, &skip, Label::kNear); 1643 __ j(not_equal, &skip, Label::kNear);
1629 __ ret(0); 1644 __ ret(0);
1630 1645
1631 // If we decide not to perform on-stack replacement we perform a 1646 // If we decide not to perform on-stack replacement we perform a
1632 // stack guard check to enable interrupts. 1647 // stack guard check to enable interrupts.
1633 __ bind(&stack_check); 1648 __ bind(&stack_check);
1634 Label ok; 1649 Label ok;
1635 ExternalReference stack_limit = 1650 ExternalReference stack_limit =
1636 ExternalReference::address_of_stack_limit(masm->isolate()); 1651 ExternalReference::address_of_stack_limit(masm->isolate());
1637 __ cmp(esp, Operand::StaticVariable(stack_limit)); 1652 __ cmp(esp, Operand::StaticVariable(stack_limit));
1638 __ j(above_equal, &ok, Label::kNear); 1653 __ j(above_equal, &ok, Label::kNear);
1639 StackCheckStub stub; 1654 StackCheckStub stub;
1640 __ TailCallStub(&stub); 1655 __ TailCallStub(&stub);
1641 __ Abort("Unreachable code: returned from tail call."); 1656 if (FLAG_debug_code) {
1657 __ Abort("Unreachable code: returned from tail call.");
1658 }
1642 __ bind(&ok); 1659 __ bind(&ok);
1643 __ ret(0); 1660 __ ret(0);
1644 1661
1645 __ bind(&skip); 1662 __ bind(&skip);
1646 // Untag the AST id and push it on the stack. 1663 // Untag the AST id and push it on the stack.
1647 __ SmiUntag(eax); 1664 __ SmiUntag(eax);
1648 __ push(eax); 1665 __ push(eax);
1649 1666
1650 // Generate the code for doing the frame-to-frame translation using 1667 // Generate the code for doing the frame-to-frame translation using
1651 // the deoptimizer infrastructure. 1668 // the deoptimizer infrastructure.
1652 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); 1669 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1653 generator.Generate(); 1670 generator.Generate();
1654 } 1671 }
1655 1672
1656 1673
1657 #undef __ 1674 #undef __
1658 } 1675 }
1659 } // namespace v8::internal 1676 } // namespace v8::internal
1660 1677
1661 #endif // V8_TARGET_ARCH_IA32 1678 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/ia32/code-stubs-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698