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

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

Issue 7050039: Revert 8122 (stub call asserts) while test failures are investigated. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 6 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 } 107 }
108 108
109 109
110 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 110 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
111 bool is_api_function, 111 bool is_api_function,
112 bool count_constructions) { 112 bool count_constructions) {
113 // Should never count constructions for api objects. 113 // Should never count constructions for api objects.
114 ASSERT(!is_api_function || !count_constructions); 114 ASSERT(!is_api_function || !count_constructions);
115 115
116 // Enter a construct frame. 116 // Enter a construct frame.
117 { 117 __ EnterConstructFrame();
118 FrameScope scope(masm, StackFrame::CONSTRUCT); 118
119 119 // Store a smi-tagged arguments count on the stack.
120 // Store a smi-tagged arguments count on the stack. 120 __ SmiTag(eax);
121 __ SmiTag(eax); 121 __ push(eax);
122 __ push(eax); 122
123 123 // Push the function to invoke on the stack.
124 // Push the function to invoke on the stack. 124 __ push(edi);
125 __ push(edi); 125
126 126 // Try to allocate the object without transitioning into C code. If any of the
127 // Try to allocate the object without transitioning into C code. If any of 127 // preconditions is not met, the code bails out to the runtime call.
128 // the preconditions is not met, the code bails out to the runtime call. 128 Label rt_call, allocated;
129 Label rt_call, allocated; 129 if (FLAG_inline_new) {
130 if (FLAG_inline_new) { 130 Label undo_allocation;
131 Label undo_allocation;
132 #ifdef ENABLE_DEBUGGER_SUPPORT 131 #ifdef ENABLE_DEBUGGER_SUPPORT
133 ExternalReference debug_step_in_fp = 132 ExternalReference debug_step_in_fp =
134 ExternalReference::debug_step_in_fp_address(masm->isolate()); 133 ExternalReference::debug_step_in_fp_address(masm->isolate());
135 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); 134 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
136 __ j(not_equal, &rt_call); 135 __ j(not_equal, &rt_call);
137 #endif 136 #endif
138 137
139 // Verified that the constructor is a JSFunction. 138 // Verified that the constructor is a JSFunction.
140 // 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.
141 // edi: constructor 140 // edi: constructor
142 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 141 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
143 // Will both indicate a NULL and a Smi 142 // Will both indicate a NULL and a Smi
144 __ test(eax, Immediate(kSmiTagMask)); 143 __ test(eax, Immediate(kSmiTagMask));
145 __ j(zero, &rt_call); 144 __ j(zero, &rt_call);
146 // edi: constructor 145 // edi: constructor
147 // eax: initial map (if proven valid below) 146 // eax: initial map (if proven valid below)
148 __ CmpObjectType(eax, MAP_TYPE, ebx); 147 __ CmpObjectType(eax, MAP_TYPE, ebx);
149 __ j(not_equal, &rt_call); 148 __ j(not_equal, &rt_call);
150 149
151 // Check that the constructor is not constructing a JSFunction (see 150 // Check that the constructor is not constructing a JSFunction (see comments
152 // comments in Runtime_NewObject in runtime.cc). In which case the initial 151 // in Runtime_NewObject in runtime.cc). In which case the initial map's
153 // map's instance type would be JS_FUNCTION_TYPE. 152 // instance type would be JS_FUNCTION_TYPE.
154 // edi: constructor 153 // edi: constructor
155 // eax: initial map 154 // eax: initial map
156 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 155 __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
157 __ j(equal, &rt_call); 156 __ j(equal, &rt_call);
158 157
158 if (count_constructions) {
159 Label allocate;
160 // Decrease generous allocation count.
161 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
162 __ dec_b(FieldOperand(ecx, SharedFunctionInfo::kConstructionCountOffset));
163 __ j(not_zero, &allocate);
164
165 __ push(eax);
166 __ push(edi);
167
168 __ push(edi); // constructor
169 // The call will replace the stub, so the countdown is only done once.
170 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
171
172 __ pop(edi);
173 __ pop(eax);
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(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
184 // Allocated the JSObject, now initialize the fields.
185 // eax: initial map
186 // ebx: JSObject
187 // edi: start of next object
188 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
189 Factory* factory = masm->isolate()->factory();
190 __ mov(ecx, factory->empty_fixed_array());
191 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
192 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
193 // Set extra fields in the newly allocated object.
194 // eax: initial map
195 // ebx: JSObject
196 // edi: start of next object
197 { Label loop, entry;
198 // To allow for truncation.
159 if (count_constructions) { 199 if (count_constructions) {
160 Label allocate; 200 __ mov(edx, factory->one_pointer_filler_map());
161 // Decrease generous allocation count. 201 } else {
162 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 202 __ mov(edx, factory->undefined_value());
163 __ dec_b(FieldOperand(ecx,
164 SharedFunctionInfo::kConstructionCountOffset));
165 __ j(not_zero, &allocate);
166
167 __ push(eax);
168 __ push(edi);
169
170 __ push(edi); // constructor
171 // The call will replace the stub, so the countdown is only done once.
172 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
173
174 __ pop(edi);
175 __ pop(eax);
176
177 __ bind(&allocate);
178 } 203 }
179 204 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
180 // Now allocate the JSObject on the heap. 205 __ jmp(&entry);
181 // edi: constructor 206 __ bind(&loop);
182 // eax: initial map 207 __ mov(Operand(ecx, 0), edx);
183 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 208 __ add(Operand(ecx), Immediate(kPointerSize));
184 __ shl(edi, kPointerSizeLog2); 209 __ bind(&entry);
185 __ AllocateInNewSpace(edi, 210 __ cmp(ecx, Operand(edi));
186 ebx, 211 __ j(less, &loop);
187 edi,
188 no_reg,
189 &rt_call,
190 NO_ALLOCATION_FLAGS);
191 // Allocated the JSObject, now initialize the fields.
192 // eax: initial map
193 // ebx: JSObject
194 // edi: start of next object
195 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
196 Factory* factory = masm->isolate()->factory();
197 __ mov(ecx, factory->empty_fixed_array());
198 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
199 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
200 // Set extra fields in the newly allocated object.
201 // eax: initial map
202 // ebx: JSObject
203 // edi: start of next object
204 { Label loop, entry;
205 // To allow for truncation.
206 if (count_constructions) {
207 __ mov(edx, factory->one_pointer_filler_map());
208 } else {
209 __ mov(edx, factory->undefined_value());
210 }
211 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
212 __ jmp(&entry);
213 __ bind(&loop);
214 __ mov(Operand(ecx, 0), edx);
215 __ add(Operand(ecx), Immediate(kPointerSize));
216 __ bind(&entry);
217 __ cmp(ecx, Operand(edi));
218 __ j(less, &loop);
219 }
220
221 // Add the object tag to make the JSObject real, so that we can continue
222 // and jump into the continuation code at any time from now on. Any
223 // failures need to undo the allocation, so that the heap is in a
224 // consistent state and verifiable.
225 // eax: initial map
226 // ebx: JSObject
227 // edi: start of next object
228 __ or_(Operand(ebx), Immediate(kHeapObjectTag));
229
230 // Check if a non-empty properties array is needed.
231 // Allocate and initialize a FixedArray if it is.
232 // eax: initial map
233 // ebx: JSObject
234 // edi: start of next object
235 // Calculate the total number of properties described by the map.
236 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
237 __ movzx_b(ecx,
238 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
239 __ add(edx, Operand(ecx));
240 // Calculate unused properties past the end of the in-object properties.
241 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
242 __ sub(edx, Operand(ecx));
243 // Done if no extra properties are to be allocated.
244 __ j(zero, &allocated);
245 __ Assert(positive, "Property allocation count failed.");
246
247 // Scale the number of elements by pointer size and add the header for
248 // FixedArrays to the start of the next object calculation from above.
249 // ebx: JSObject
250 // edi: start of next object (will be start of FixedArray)
251 // edx: number of elements in properties array
252 __ AllocateInNewSpace(FixedArray::kHeaderSize,
253 times_pointer_size,
254 edx,
255 edi,
256 ecx,
257 no_reg,
258 &undo_allocation,
259 RESULT_CONTAINS_TOP);
260
261 // Initialize the FixedArray.
262 // ebx: JSObject
263 // edi: FixedArray
264 // edx: number of elements
265 // ecx: start of next object
266 __ mov(eax, factory->fixed_array_map());
267 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
268 __ SmiTag(edx);
269 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
270
271 // Initialize the fields to undefined.
272 // ebx: JSObject
273 // edi: FixedArray
274 // ecx: start of next object
275 { Label loop, entry;
276 __ mov(edx, factory->undefined_value());
277 __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
278 __ jmp(&entry);
279 __ bind(&loop);
280 __ mov(Operand(eax, 0), edx);
281 __ add(Operand(eax), Immediate(kPointerSize));
282 __ bind(&entry);
283 __ cmp(eax, Operand(ecx));
284 __ j(below, &loop);
285 }
286
287 // Store the initialized FixedArray into the properties field of
288 // the JSObject
289 // ebx: JSObject
290 // edi: FixedArray
291 __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag
292 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
293
294
295 // Continue with JSObject being successfully allocated
296 // ebx: JSObject
297 __ jmp(&allocated);
298
299 // Undo the setting of the new top so that the heap is verifiable. For
300 // example, the map's unused properties potentially do not match the
301 // allocated objects unused properties.
302 // ebx: JSObject (previous new top)
303 __ bind(&undo_allocation);
304 __ UndoAllocationInNewSpace(ebx);
305 } 212 }
306 213
307 // Allocate the new receiver object using the runtime call. 214 // Add the object tag to make the JSObject real, so that we can continue and
308 __ bind(&rt_call); 215 // jump into the continuation code at any time from now on. Any failures
309 // Must restore edi (constructor) before calling runtime. 216 // need to undo the allocation, so that the heap is in a consistent state
310 __ mov(edi, Operand(esp, 0)); 217 // and verifiable.
311 // edi: function (constructor) 218 // eax: initial map
312 __ push(edi); 219 // ebx: JSObject
313 __ CallRuntime(Runtime::kNewObject, 1); 220 // edi: start of next object
314 __ mov(ebx, Operand(eax)); // store result in ebx 221 __ or_(Operand(ebx), Immediate(kHeapObjectTag));
315 222
316 // New object allocated. 223 // Check if a non-empty properties array is needed.
317 // ebx: newly allocated object 224 // Allocate and initialize a FixedArray if it is.
318 __ bind(&allocated); 225 // eax: initial map
319 // Retrieve the function from the stack. 226 // ebx: JSObject
320 __ pop(edi); 227 // edi: start of next object
321 228 // Calculate the total number of properties described by the map.
322 // Retrieve smi-tagged arguments count from the stack. 229 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
323 __ mov(eax, Operand(esp, 0)); 230 __ movzx_b(ecx, FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
324 __ SmiUntag(eax); 231 __ add(edx, Operand(ecx));
325 232 // Calculate unused properties past the end of the in-object properties.
326 // Push the allocated receiver to the stack. We need two copies 233 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
327 // because we may have to return the original one and the calling 234 __ sub(edx, Operand(ecx));
328 // conventions dictate that the called function pops the receiver. 235 // Done if no extra properties are to be allocated.
329 __ push(ebx); 236 __ j(zero, &allocated);
330 __ push(ebx); 237 __ Assert(positive, "Property allocation count failed.");
331 238
332 // Setup pointer to last argument. 239 // Scale the number of elements by pointer size and add the header for
333 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 240 // FixedArrays to the start of the next object calculation from above.
334 241 // ebx: JSObject
335 // Copy arguments and receiver to the expression stack. 242 // edi: start of next object (will be start of FixedArray)
336 Label loop, entry; 243 // edx: number of elements in properties array
337 __ mov(ecx, Operand(eax)); 244 __ AllocateInNewSpace(FixedArray::kHeaderSize,
338 __ jmp(&entry); 245 times_pointer_size,
339 __ bind(&loop); 246 edx,
340 __ push(Operand(ebx, ecx, times_4, 0)); 247 edi,
341 __ bind(&entry); 248 ecx,
342 __ dec(ecx); 249 no_reg,
343 __ j(greater_equal, &loop); 250 &undo_allocation,
344 251 RESULT_CONTAINS_TOP);
345 // Call the function. 252
346 if (is_api_function) { 253 // Initialize the FixedArray.
347 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 254 // ebx: JSObject
348 Handle<Code> code = 255 // edi: FixedArray
349 masm->isolate()->builtins()->HandleApiCallConstruct(); 256 // edx: number of elements
350 ParameterCount expected(0); 257 // ecx: start of next object
351 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, 258 __ mov(eax, factory->fixed_array_map());
352 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 259 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
353 } else { 260 __ SmiTag(edx);
354 ParameterCount actual(eax); 261 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
355 __ InvokeFunction(edi, actual, CALL_FUNCTION, 262
356 NullCallWrapper(), CALL_AS_METHOD); 263 // Initialize the fields to undefined.
264 // ebx: JSObject
265 // edi: FixedArray
266 // ecx: start of next object
267 { Label loop, entry;
268 __ mov(edx, factory->undefined_value());
269 __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
270 __ jmp(&entry);
271 __ bind(&loop);
272 __ mov(Operand(eax, 0), edx);
273 __ add(Operand(eax), Immediate(kPointerSize));
274 __ bind(&entry);
275 __ cmp(eax, Operand(ecx));
276 __ j(below, &loop);
357 } 277 }
358 278
359 // Restore context from the frame. 279 // Store the initialized FixedArray into the properties field of
360 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 280 // the JSObject
361 281 // ebx: JSObject
362 // If the result is an object (in the ECMA sense), we should get rid 282 // edi: FixedArray
363 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 283 __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag
364 // on page 74. 284 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
365 Label use_receiver, exit; 285
366 286
367 // If the result is a smi, it is *not* an object in the ECMA sense. 287 // Continue with JSObject being successfully allocated
368 __ test(eax, Immediate(kSmiTagMask)); 288 // ebx: JSObject
369 __ j(zero, &use_receiver); 289 __ jmp(&allocated);
370 290
371 // If the type of the result (stored in its map) is less than 291 // Undo the setting of the new top so that the heap is verifiable. For
372 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. 292 // example, the map's unused properties potentially do not match the
373 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 293 // allocated objects unused properties.
374 __ j(above_equal, &exit); 294 // ebx: JSObject (previous new top)
375 295 __ bind(&undo_allocation);
376 // Throw away the result of the constructor invocation and use the 296 __ UndoAllocationInNewSpace(ebx);
377 // on-stack receiver as the result.
378 __ bind(&use_receiver);
379 __ mov(eax, Operand(esp, 0));
380
381 // Restore the arguments count and leave the construct frame.
382 __ bind(&exit);
383 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count
384
385 // Leave construct frame.
386 } 297 }
387 298
299 // Allocate the new receiver object using the runtime call.
300 __ bind(&rt_call);
301 // Must restore edi (constructor) before calling runtime.
302 __ mov(edi, Operand(esp, 0));
303 // edi: function (constructor)
304 __ push(edi);
305 __ CallRuntime(Runtime::kNewObject, 1);
306 __ mov(ebx, Operand(eax)); // store result in ebx
307
308 // New object allocated.
309 // ebx: newly allocated object
310 __ bind(&allocated);
311 // Retrieve the function from the stack.
312 __ pop(edi);
313
314 // Retrieve smi-tagged arguments count from the stack.
315 __ mov(eax, Operand(esp, 0));
316 __ SmiUntag(eax);
317
318 // Push the allocated receiver to the stack. We need two copies
319 // because we may have to return the original one and the calling
320 // conventions dictate that the called function pops the receiver.
321 __ push(ebx);
322 __ push(ebx);
323
324 // Setup pointer to last argument.
325 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
326
327 // Copy arguments and receiver to the expression stack.
328 Label loop, entry;
329 __ mov(ecx, Operand(eax));
330 __ jmp(&entry);
331 __ bind(&loop);
332 __ push(Operand(ebx, ecx, times_4, 0));
333 __ bind(&entry);
334 __ dec(ecx);
335 __ j(greater_equal, &loop);
336
337 // Call the function.
338 if (is_api_function) {
339 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
340 Handle<Code> code =
341 masm->isolate()->builtins()->HandleApiCallConstruct();
342 ParameterCount expected(0);
343 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
344 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
345 } else {
346 ParameterCount actual(eax);
347 __ InvokeFunction(edi, actual, CALL_FUNCTION,
348 NullCallWrapper(), CALL_AS_METHOD);
349 }
350
351 // Restore context from the frame.
352 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
353
354 // If the result is an object (in the ECMA sense), we should get rid
355 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
356 // on page 74.
357 Label use_receiver, exit;
358
359 // If the result is a smi, it is *not* an object in the ECMA sense.
360 __ test(eax, Immediate(kSmiTagMask));
361 __ j(zero, &use_receiver);
362
363 // If the type of the result (stored in its map) is less than
364 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
365 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
366 __ j(above_equal, &exit);
367
368 // Throw away the result of the constructor invocation and use the
369 // on-stack receiver as the result.
370 __ bind(&use_receiver);
371 __ mov(eax, Operand(esp, 0));
372
373 // Restore the arguments count and leave the construct frame.
374 __ bind(&exit);
375 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count
376 __ LeaveConstructFrame();
377
388 // Remove caller arguments from the stack and return. 378 // Remove caller arguments from the stack and return.
389 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 379 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
390 __ pop(ecx); 380 __ pop(ecx);
391 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 381 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
392 __ push(ecx); 382 __ push(ecx);
393 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 383 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
394 __ ret(0); 384 __ ret(0);
395 } 385 }
396 386
397 387
398 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 388 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
399 Generate_JSConstructStubHelper(masm, false, true); 389 Generate_JSConstructStubHelper(masm, false, true);
400 } 390 }
401 391
402 392
403 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 393 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
404 Generate_JSConstructStubHelper(masm, false, false); 394 Generate_JSConstructStubHelper(masm, false, false);
405 } 395 }
406 396
407 397
408 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 398 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
409 Generate_JSConstructStubHelper(masm, true, false); 399 Generate_JSConstructStubHelper(masm, true, false);
410 } 400 }
411 401
412 402
413 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 403 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
414 bool is_construct) { 404 bool is_construct) {
415 // Clear the context before we push it when entering the internal frame. 405 // Clear the context before we push it when entering the JS frame.
416 __ Set(esi, Immediate(0)); 406 __ Set(esi, Immediate(0));
417 407
418 { 408 // Enter an internal frame.
419 FrameScope scope(masm, StackFrame::INTERNAL); 409 __ EnterInternalFrame();
420 410
421 // Load the previous frame pointer (ebx) to access C arguments 411 // Load the previous frame pointer (ebx) to access C arguments
422 __ mov(ebx, Operand(ebp, 0)); 412 __ mov(ebx, Operand(ebp, 0));
423 413
424 // Get the function from the frame and setup the context. 414 // Get the function from the frame and setup the context.
425 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 415 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
426 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); 416 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));
427 417
428 // Push the function and the receiver onto the stack. 418 // Push the function and the receiver onto the stack.
429 __ push(ecx); 419 __ push(ecx);
430 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 420 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
431 421
432 // Load the number of arguments and setup pointer to the arguments. 422 // Load the number of arguments and setup pointer to the arguments.
433 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 423 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
434 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 424 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
435 425
436 // Copy arguments to the stack in a loop. 426 // Copy arguments to the stack in a loop.
437 Label loop, entry; 427 Label loop, entry;
438 __ Set(ecx, Immediate(0)); 428 __ Set(ecx, Immediate(0));
439 __ jmp(&entry); 429 __ jmp(&entry);
440 __ bind(&loop); 430 __ bind(&loop);
441 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 431 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv
442 __ push(Operand(edx, 0)); // dereference handle 432 __ push(Operand(edx, 0)); // dereference handle
443 __ inc(Operand(ecx)); 433 __ inc(Operand(ecx));
444 __ bind(&entry); 434 __ bind(&entry);
445 __ cmp(ecx, Operand(eax)); 435 __ cmp(ecx, Operand(eax));
446 __ j(not_equal, &loop); 436 __ j(not_equal, &loop);
447 437
448 // Get the function from the stack and call it. 438 // Get the function from the stack and call it.
449 // kPointerSize for the receiver. 439 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver
450 __ mov(edi, Operand(esp, eax, times_4, kPointerSize));
451 440
452 // Invoke the code. 441 // Invoke the code.
453 if (is_construct) { 442 if (is_construct) {
454 __ call(masm->isolate()->builtins()->JSConstructCall(), 443 __ call(masm->isolate()->builtins()->JSConstructCall(),
455 RelocInfo::CODE_TARGET); 444 RelocInfo::CODE_TARGET);
456 } else { 445 } else {
457 ParameterCount actual(eax); 446 ParameterCount actual(eax);
458 __ InvokeFunction(edi, actual, CALL_FUNCTION, 447 __ InvokeFunction(edi, actual, CALL_FUNCTION,
459 NullCallWrapper(), CALL_AS_METHOD); 448 NullCallWrapper(), CALL_AS_METHOD);
460 } 449 }
461 450
462 // Exit the internal frame. Notice that this also removes the empty. 451 // Exit the JS frame. Notice that this also removes the empty
463 // context and the function left on the stack by the code 452 // context and the function left on the stack by the code
464 // invocation. 453 // invocation.
465 } 454 __ LeaveInternalFrame();
466 __ ret(kPointerSize); // Remove receiver. 455 __ ret(1 * kPointerSize); // remove receiver
467 } 456 }
468 457
469 458
470 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 459 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
471 Generate_JSEntryTrampolineHelper(masm, false); 460 Generate_JSEntryTrampolineHelper(masm, false);
472 } 461 }
473 462
474 463
475 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 464 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
476 Generate_JSEntryTrampolineHelper(masm, true); 465 Generate_JSEntryTrampolineHelper(masm, true);
477 } 466 }
478 467
479 468
480 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { 469 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
481 { 470 // Enter an internal frame.
482 FrameScope scope(masm, StackFrame::INTERNAL); 471 __ EnterInternalFrame();
483 472
484 // Push a copy of the function. 473 // Push a copy of the function.
485 __ push(edi); 474 __ push(edi);
486 // Push call kind information. 475 // Push call kind information.
487 __ push(ecx); 476 __ push(ecx);
488 477
489 __ push(edi); // Function is also the parameter to the runtime call. 478 __ push(edi); // Function is also the parameter to the runtime call.
490 __ CallRuntime(Runtime::kLazyCompile, 1); 479 __ CallRuntime(Runtime::kLazyCompile, 1);
491 480
492 // Restore call kind information. 481 // Restore call kind information.
493 __ pop(ecx); 482 __ pop(ecx);
494 // Restore receiver. 483 // Restore receiver.
495 __ pop(edi); 484 __ pop(edi);
496 485
497 // Tear down internal frame. 486 // Tear down temporary frame.
498 } 487 __ LeaveInternalFrame();
499 488
500 // Do a tail-call of the compiled function. 489 // Do a tail-call of the compiled function.
501 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 490 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
502 __ jmp(Operand(eax)); 491 __ jmp(Operand(eax));
503 } 492 }
504 493
505 494
506 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 495 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
507 { 496 // Enter an internal frame.
508 FrameScope scope(masm, StackFrame::INTERNAL); 497 __ EnterInternalFrame();
509 498
510 // Push a copy of the function onto the stack. 499 // Push a copy of the function onto the stack.
511 __ push(edi); 500 __ push(edi);
512 // Push call kind information. 501 // Push call kind information.
513 __ push(ecx); 502 __ push(ecx);
514 503
515 __ push(edi); // Function is also the parameter to the runtime call. 504 __ push(edi); // Function is also the parameter to the runtime call.
516 __ CallRuntime(Runtime::kLazyRecompile, 1); 505 __ CallRuntime(Runtime::kLazyRecompile, 1);
517 506
518 // Restore call kind information. 507 // Restore call kind information.
519 __ pop(ecx); 508 __ pop(ecx);
520 // Restore receiver. 509 // Restore receiver.
521 __ pop(edi); 510 __ pop(edi);
522 511
523 // Tear down internal frame. 512 // Tear down temporary frame.
524 } 513 __ LeaveInternalFrame();
525 514
526 // Do a tail-call of the compiled function. 515 // Do a tail-call of the compiled function.
527 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 516 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
528 __ jmp(Operand(eax)); 517 __ jmp(Operand(eax));
529 } 518 }
530 519
531 520
532 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 521 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
533 Deoptimizer::BailoutType type) { 522 Deoptimizer::BailoutType type) {
534 { 523 // Enter an internal frame.
535 FrameScope scope(masm, StackFrame::INTERNAL); 524 __ EnterInternalFrame();
536 525
537 // Pass the function and deoptimization type to the runtime system. 526 // Pass the function and deoptimization type to the runtime system.
538 __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 527 __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
539 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 528 __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
540 529
541 // Tear down internal frame. 530 // Tear down temporary frame.
542 } 531 __ LeaveInternalFrame();
543 532
544 // Get the full codegen state from the stack and untag it. 533 // Get the full codegen state from the stack and untag it.
545 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 534 __ mov(ecx, Operand(esp, 1 * kPointerSize));
546 __ SmiUntag(ecx); 535 __ SmiUntag(ecx);
547 536
548 // Switch on the state. 537 // Switch on the state.
549 Label not_no_registers, not_tos_eax; 538 Label not_no_registers, not_tos_eax;
550 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); 539 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
551 __ j(not_equal, &not_no_registers, Label::kNear); 540 __ j(not_equal, &not_no_registers, Label::kNear);
552 __ ret(1 * kPointerSize); // Remove state. 541 __ ret(1 * kPointerSize); // Remove state.
(...skipping 20 matching lines...) Expand all
573 562
574 563
575 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { 564 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
576 // TODO(kasperl): Do we need to save/restore the XMM registers too? 565 // TODO(kasperl): Do we need to save/restore the XMM registers too?
577 566
578 // For now, we are relying on the fact that Runtime::NotifyOSR 567 // For now, we are relying on the fact that Runtime::NotifyOSR
579 // doesn't do any garbage collection which allows us to save/restore 568 // doesn't do any garbage collection which allows us to save/restore
580 // the registers without worrying about which of them contain 569 // the registers without worrying about which of them contain
581 // pointers. This seems a bit fragile. 570 // pointers. This seems a bit fragile.
582 __ pushad(); 571 __ pushad();
583 { 572 __ EnterInternalFrame();
584 FrameScope scope(masm, StackFrame::INTERNAL); 573 __ CallRuntime(Runtime::kNotifyOSR, 0);
585 __ CallRuntime(Runtime::kNotifyOSR, 0); 574 __ LeaveInternalFrame();
586 }
587 __ popad(); 575 __ popad();
588 __ ret(0); 576 __ ret(0);
589 } 577 }
590 578
591 579
592 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 580 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
593 Factory* factory = masm->isolate()->factory(); 581 Factory* factory = masm->isolate()->factory();
594 582
595 // 1. Make sure we have at least one argument. 583 // 1. Make sure we have at least one argument.
596 { Label done; 584 { Label done;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 __ cmp(ebx, factory->null_value()); 629 __ cmp(ebx, factory->null_value());
642 __ j(equal, &use_global_receiver); 630 __ j(equal, &use_global_receiver);
643 __ cmp(ebx, factory->undefined_value()); 631 __ cmp(ebx, factory->undefined_value());
644 __ j(equal, &use_global_receiver); 632 __ j(equal, &use_global_receiver);
645 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); 633 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
646 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 634 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
647 __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx); 635 __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx);
648 __ j(above_equal, &shift_arguments); 636 __ j(above_equal, &shift_arguments);
649 637
650 __ bind(&convert_to_object); 638 __ bind(&convert_to_object);
639 __ EnterInternalFrame(); // In order to preserve argument count.
640 __ SmiTag(eax);
641 __ push(eax);
651 642
652 { // In order to preserve argument count. 643 __ push(ebx);
653 FrameScope scope(masm, StackFrame::INTERNAL); 644 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
654 __ SmiTag(eax); 645 __ mov(ebx, eax);
655 __ push(eax);
656 646
657 __ push(ebx); 647 __ pop(eax);
658 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 648 __ SmiUntag(eax);
659 __ mov(ebx, eax); 649 __ LeaveInternalFrame();
660
661 __ pop(eax);
662 __ SmiUntag(eax);
663 }
664
665 // Restore the function to edi. 650 // Restore the function to edi.
666 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 651 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
667 __ jmp(&patch_receiver); 652 __ jmp(&patch_receiver);
668 653
669 // Use the global receiver object from the called function as the 654 // Use the global receiver object from the called function as the
670 // receiver. 655 // receiver.
671 __ bind(&use_global_receiver); 656 __ bind(&use_global_receiver);
672 const int kGlobalIndex = 657 const int kGlobalIndex =
673 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 658 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
674 __ mov(ebx, FieldOperand(esi, kGlobalIndex)); 659 __ mov(ebx, FieldOperand(esi, kGlobalIndex));
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 __ j(not_equal, 716 __ j(not_equal,
732 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); 717 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
733 718
734 ParameterCount expected(0); 719 ParameterCount expected(0);
735 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION, 720 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION,
736 NullCallWrapper(), CALL_AS_METHOD); 721 NullCallWrapper(), CALL_AS_METHOD);
737 } 722 }
738 723
739 724
740 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 725 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
741 { 726 __ EnterInternalFrame();
742 FrameScope scope(masm, StackFrame::INTERNAL);
743 727
744 __ push(Operand(ebp, 4 * kPointerSize)); // push this 728 __ push(Operand(ebp, 4 * kPointerSize)); // push this
745 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments 729 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments
746 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 730 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
747 731
748 // Check the stack for overflow. We are not trying need to catch 732 // Check the stack for overflow. We are not trying need to catch
749 // interruptions (e.g. debug break and preemption) here, so the "real stack 733 // interruptions (e.g. debug break and preemption) here, so the "real stack
750 // limit" is checked. 734 // limit" is checked.
751 Label okay; 735 Label okay;
752 ExternalReference real_stack_limit = 736 ExternalReference real_stack_limit =
753 ExternalReference::address_of_real_stack_limit(masm->isolate()); 737 ExternalReference::address_of_real_stack_limit(masm->isolate());
754 __ mov(edi, Operand::StaticVariable(real_stack_limit)); 738 __ mov(edi, Operand::StaticVariable(real_stack_limit));
755 // Make ecx the space we have left. The stack might already be overflowed 739 // Make ecx the space we have left. The stack might already be overflowed
756 // here which will cause ecx to become negative. 740 // here which will cause ecx to become negative.
757 __ mov(ecx, Operand(esp)); 741 __ mov(ecx, Operand(esp));
758 __ sub(ecx, Operand(edi)); 742 __ sub(ecx, Operand(edi));
759 // Make edx the space we need for the array when it is unrolled onto the 743 // Make edx the space we need for the array when it is unrolled onto the
760 // stack. 744 // stack.
761 __ mov(edx, Operand(eax)); 745 __ mov(edx, Operand(eax));
762 __ shl(edx, kPointerSizeLog2 - kSmiTagSize); 746 __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
763 // Check if the arguments will overflow the stack. 747 // Check if the arguments will overflow the stack.
764 __ cmp(ecx, Operand(edx)); 748 __ cmp(ecx, Operand(edx));
765 __ j(greater, &okay); // Signed comparison. 749 __ j(greater, &okay); // Signed comparison.
766 750
767 // Out of stack space. 751 // Out of stack space.
768 __ push(Operand(ebp, 4 * kPointerSize)); // push this 752 __ push(Operand(ebp, 4 * kPointerSize)); // push this
769 __ push(eax); 753 __ push(eax);
770 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 754 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
771 __ bind(&okay); 755 __ bind(&okay);
772 // End of stack check. 756 // End of stack check.
773 757
774 // Push current index and limit. 758 // Push current index and limit.
775 const int kLimitOffset = 759 const int kLimitOffset =
776 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 760 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
777 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 761 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
778 __ push(eax); // limit 762 __ push(eax); // limit
779 __ push(Immediate(0)); // index 763 __ push(Immediate(0)); // index
780 764
781 // Change context eagerly to get the right global object if 765 // Change context eagerly to get the right global object if
782 // necessary. 766 // necessary.
783 __ mov(edi, Operand(ebp, 4 * kPointerSize)); 767 __ mov(edi, Operand(ebp, 4 * kPointerSize));
784 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 768 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
785 769
786 // Compute the receiver. 770 // Compute the receiver.
787 Label call_to_object, use_global_receiver, push_receiver; 771 Label call_to_object, use_global_receiver, push_receiver;
788 __ mov(ebx, Operand(ebp, 3 * kPointerSize)); 772 __ mov(ebx, Operand(ebp, 3 * kPointerSize));
789 773
790 // Do not transform the receiver for strict mode functions. 774 // Do not transform the receiver for strict mode functions.
791 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 775 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
792 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 776 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
793 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 777 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
794 __ j(not_equal, &push_receiver); 778 __ j(not_equal, &push_receiver);
795 779
796 Factory* factory = masm->isolate()->factory(); 780 Factory* factory = masm->isolate()->factory();
797 781
798 // Do not transform the receiver for natives (shared already in ecx). 782 // Do not transform the receiver for natives (shared already in ecx).
799 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), 783 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
800 1 << SharedFunctionInfo::kNativeBitWithinByte); 784 1 << SharedFunctionInfo::kNativeBitWithinByte);
801 __ j(not_equal, &push_receiver); 785 __ j(not_equal, &push_receiver);
802 786
803 // Compute the receiver in non-strict mode. 787 // Compute the receiver in non-strict mode.
804 // Call ToObject on the receiver if it is not an object, or use the 788 // Call ToObject on the receiver if it is not an object, or use the
805 // global object if it is null or undefined. 789 // global object if it is null or undefined.
806 __ test(ebx, Immediate(kSmiTagMask)); 790 __ test(ebx, Immediate(kSmiTagMask));
807 __ j(zero, &call_to_object); 791 __ j(zero, &call_to_object);
808 __ cmp(ebx, factory->null_value()); 792 __ cmp(ebx, factory->null_value());
809 __ j(equal, &use_global_receiver); 793 __ j(equal, &use_global_receiver);
810 __ cmp(ebx, factory->undefined_value()); 794 __ cmp(ebx, factory->undefined_value());
811 __ j(equal, &use_global_receiver); 795 __ j(equal, &use_global_receiver);
812 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); 796 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE);
813 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 797 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
814 __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx); 798 __ CmpObjectType(ebx, FIRST_JS_OBJECT_TYPE, ecx);
815 __ j(above_equal, &push_receiver); 799 __ j(above_equal, &push_receiver);
816 800
817 __ bind(&call_to_object); 801 __ bind(&call_to_object);
818 __ push(ebx); 802 __ push(ebx);
819 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 803 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
820 __ mov(ebx, Operand(eax)); 804 __ mov(ebx, Operand(eax));
821 __ jmp(&push_receiver); 805 __ jmp(&push_receiver);
822 806
823 // Use the current global receiver object as the receiver. 807 // Use the current global receiver object as the receiver.
824 __ bind(&use_global_receiver); 808 __ bind(&use_global_receiver);
825 const int kGlobalOffset = 809 const int kGlobalOffset =
826 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 810 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
827 __ mov(ebx, FieldOperand(esi, kGlobalOffset)); 811 __ mov(ebx, FieldOperand(esi, kGlobalOffset));
828 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset)); 812 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset));
829 __ mov(ebx, FieldOperand(ebx, kGlobalOffset)); 813 __ mov(ebx, FieldOperand(ebx, kGlobalOffset));
830 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 814 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
831 815
832 // Push the receiver. 816 // Push the receiver.
833 __ bind(&push_receiver); 817 __ bind(&push_receiver);
834 __ push(ebx); 818 __ push(ebx);
835 819
836 // Copy all arguments from the array to the stack. 820 // Copy all arguments from the array to the stack.
837 Label entry, loop; 821 Label entry, loop;
838 __ mov(eax, Operand(ebp, kIndexOffset)); 822 __ mov(eax, Operand(ebp, kIndexOffset));
839 __ jmp(&entry); 823 __ jmp(&entry);
840 __ bind(&loop); 824 __ bind(&loop);
841 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments 825 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments
842 826
843 // Use inline caching to speed up access to arguments. 827 // Use inline caching to speed up access to arguments.
844 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize(); 828 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
845 __ call(ic, RelocInfo::CODE_TARGET); 829 __ call(ic, RelocInfo::CODE_TARGET);
846 // It is important that we do not have a test instruction after the 830 // It is important that we do not have a test instruction after the
847 // call. A test instruction after the call is used to indicate that 831 // call. A test instruction after the call is used to indicate that
848 // we have generated an inline version of the keyed load. In this 832 // we have generated an inline version of the keyed load. In this
849 // case, we know that we are not generating a test instruction next. 833 // case, we know that we are not generating a test instruction next.
850 834
851 // Push the nth argument. 835 // Push the nth argument.
852 __ push(eax); 836 __ push(eax);
853 837
854 // Update the index on the stack and in register eax. 838 // Update the index on the stack and in register eax.
855 __ mov(eax, Operand(ebp, kIndexOffset)); 839 __ mov(eax, Operand(ebp, kIndexOffset));
856 __ add(Operand(eax), Immediate(1 << kSmiTagSize)); 840 __ add(Operand(eax), Immediate(1 << kSmiTagSize));
857 __ mov(Operand(ebp, kIndexOffset), eax); 841 __ mov(Operand(ebp, kIndexOffset), eax);
858 842
859 __ bind(&entry); 843 __ bind(&entry);
860 __ cmp(eax, Operand(ebp, kLimitOffset)); 844 __ cmp(eax, Operand(ebp, kLimitOffset));
861 __ j(not_equal, &loop); 845 __ j(not_equal, &loop);
862 846
863 // Invoke the function. 847 // Invoke the function.
864 ParameterCount actual(eax); 848 ParameterCount actual(eax);
865 __ SmiUntag(eax); 849 __ SmiUntag(eax);
866 __ mov(edi, Operand(ebp, 4 * kPointerSize)); 850 __ mov(edi, Operand(ebp, 4 * kPointerSize));
867 __ InvokeFunction(edi, actual, CALL_FUNCTION, 851 __ InvokeFunction(edi, actual, CALL_FUNCTION,
868 NullCallWrapper(), CALL_AS_METHOD); 852 NullCallWrapper(), CALL_AS_METHOD);
869 853
870 // Leave the internal frame. 854 __ LeaveInternalFrame();
871 }
872 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 855 __ ret(3 * kPointerSize); // remove this, receiver, and arguments
873 } 856 }
874 857
875 858
876 // Number of empty elements to allocate for an empty array. 859 // Number of empty elements to allocate for an empty array.
877 static const int kPreallocatedArrayElements = 4; 860 static const int kPreallocatedArrayElements = 4;
878 861
879 862
880 // Allocate an empty JSArray. The allocated array is put into the result 863 // Allocate an empty JSArray. The allocated array is put into the result
881 // register. If the parameter initial_capacity is larger than zero an elements 864 // register. If the parameter initial_capacity is larger than zero an elements
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 __ j(zero, &convert_argument); 1396 __ j(zero, &convert_argument);
1414 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); 1397 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
1415 __ j(NegateCondition(is_string), &convert_argument); 1398 __ j(NegateCondition(is_string), &convert_argument);
1416 __ mov(ebx, eax); 1399 __ mov(ebx, eax);
1417 __ IncrementCounter(counters->string_ctor_string_value(), 1); 1400 __ IncrementCounter(counters->string_ctor_string_value(), 1);
1418 __ jmp(&argument_is_string); 1401 __ jmp(&argument_is_string);
1419 1402
1420 // Invoke the conversion builtin and put the result into ebx. 1403 // Invoke the conversion builtin and put the result into ebx.
1421 __ bind(&convert_argument); 1404 __ bind(&convert_argument);
1422 __ IncrementCounter(counters->string_ctor_conversions(), 1); 1405 __ IncrementCounter(counters->string_ctor_conversions(), 1);
1423 { 1406 __ EnterInternalFrame();
1424 FrameScope scope(masm, StackFrame::INTERNAL); 1407 __ push(edi); // Preserve the function.
1425 __ push(edi); // Preserve the function. 1408 __ push(eax);
1426 __ push(eax); 1409 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1427 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 1410 __ pop(edi);
1428 __ pop(edi); 1411 __ LeaveInternalFrame();
1429 }
1430 __ mov(ebx, eax); 1412 __ mov(ebx, eax);
1431 __ jmp(&argument_is_string); 1413 __ jmp(&argument_is_string);
1432 1414
1433 // Load the empty string into ebx, remove the receiver from the 1415 // Load the empty string into ebx, remove the receiver from the
1434 // stack, and jump back to the case where the argument is a string. 1416 // stack, and jump back to the case where the argument is a string.
1435 __ bind(&no_arguments); 1417 __ bind(&no_arguments);
1436 __ Set(ebx, Immediate(factory->empty_string())); 1418 __ Set(ebx, Immediate(factory->empty_string()));
1437 __ pop(ecx); 1419 __ pop(ecx);
1438 __ lea(esp, Operand(esp, kPointerSize)); 1420 __ lea(esp, Operand(esp, kPointerSize));
1439 __ push(ecx); 1421 __ push(ecx);
1440 __ jmp(&argument_is_string); 1422 __ jmp(&argument_is_string);
1441 1423
1442 // At this point the argument is already a string. Call runtime to 1424 // At this point the argument is already a string. Call runtime to
1443 // create a string wrapper. 1425 // create a string wrapper.
1444 __ bind(&gc_required); 1426 __ bind(&gc_required);
1445 __ IncrementCounter(counters->string_ctor_gc_required(), 1); 1427 __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1446 { 1428 __ EnterInternalFrame();
1447 FrameScope scope(masm, StackFrame::INTERNAL); 1429 __ push(ebx);
1448 __ push(ebx); 1430 __ CallRuntime(Runtime::kNewStringWrapper, 1);
1449 __ CallRuntime(Runtime::kNewStringWrapper, 1); 1431 __ LeaveInternalFrame();
1450 }
1451 __ ret(0); 1432 __ ret(0);
1452 } 1433 }
1453 1434
1454 1435
1455 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1436 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1456 __ push(ebp); 1437 __ push(ebp);
1457 __ mov(ebp, Operand(esp)); 1438 __ mov(ebp, Operand(esp));
1458 1439
1459 // Store the arguments adaptor context sentinel. 1440 // Store the arguments adaptor context sentinel.
1460 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1441 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 // ------------------------------------------- 1546 // -------------------------------------------
1566 // Dont adapt arguments. 1547 // Dont adapt arguments.
1567 // ------------------------------------------- 1548 // -------------------------------------------
1568 __ bind(&dont_adapt_arguments); 1549 __ bind(&dont_adapt_arguments);
1569 __ jmp(Operand(edx)); 1550 __ jmp(Operand(edx));
1570 } 1551 }
1571 1552
1572 1553
1573 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1554 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1574 CpuFeatures::TryForceFeatureScope scope(SSE2); 1555 CpuFeatures::TryForceFeatureScope scope(SSE2);
1575 if (!CpuFeatures::IsSupported(SSE2) && FLAG_debug_code) { 1556 if (!CpuFeatures::IsSupported(SSE2)) {
1576 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); 1557 __ Abort("Unreachable code: Cannot optimize without SSE2 support.");
1577 return; 1558 return;
1578 } 1559 }
1579 1560
1580 // Get the loop depth of the stack guard check. This is recorded in 1561 // Get the loop depth of the stack guard check. This is recorded in
1581 // a test(eax, depth) instruction right after the call. 1562 // a test(eax, depth) instruction right after the call.
1582 Label stack_check; 1563 Label stack_check;
1583 __ mov(ebx, Operand(esp, 0)); // return address 1564 __ mov(ebx, Operand(esp, 0)); // return address
1584 if (FLAG_debug_code) { 1565 if (FLAG_debug_code) {
1585 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte); 1566 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte);
1586 __ Assert(equal, "test eax instruction not found after loop stack check"); 1567 __ Assert(equal, "test eax instruction not found after loop stack check");
1587 } 1568 }
1588 __ movzx_b(ebx, Operand(ebx, 1)); // depth 1569 __ movzx_b(ebx, Operand(ebx, 1)); // depth
1589 1570
1590 // Get the loop nesting level at which we allow OSR from the 1571 // Get the loop nesting level at which we allow OSR from the
1591 // unoptimized code and check if we want to do OSR yet. If not we 1572 // unoptimized code and check if we want to do OSR yet. If not we
1592 // should perform a stack guard check so we can get interrupts while 1573 // should perform a stack guard check so we can get interrupts while
1593 // waiting for on-stack replacement. 1574 // waiting for on-stack replacement.
1594 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1575 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1595 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 1576 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
1596 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); 1577 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset));
1597 __ cmpb(ebx, FieldOperand(ecx, Code::kAllowOSRAtLoopNestingLevelOffset)); 1578 __ cmpb(ebx, FieldOperand(ecx, Code::kAllowOSRAtLoopNestingLevelOffset));
1598 __ j(greater, &stack_check); 1579 __ j(greater, &stack_check);
1599 1580
1600 // Pass the function to optimize as the argument to the on-stack 1581 // Pass the function to optimize as the argument to the on-stack
1601 // replacement runtime function. 1582 // replacement runtime function.
1602 { 1583 __ EnterInternalFrame();
1603 FrameScope scope(masm, StackFrame::INTERNAL); 1584 __ push(eax);
1604 __ push(eax); 1585 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1605 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1586 __ LeaveInternalFrame();
1606 }
1607 1587
1608 // If the result was -1 it means that we couldn't optimize the 1588 // If the result was -1 it means that we couldn't optimize the
1609 // function. Just return and continue in the unoptimized version. 1589 // function. Just return and continue in the unoptimized version.
1610 Label skip; 1590 Label skip;
1611 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); 1591 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1)));
1612 __ j(not_equal, &skip, Label::kNear); 1592 __ j(not_equal, &skip, Label::kNear);
1613 __ ret(0); 1593 __ ret(0);
1614 1594
1615 // If we decide not to perform on-stack replacement we perform a 1595 // If we decide not to perform on-stack replacement we perform a
1616 // stack guard check to enable interrupts. 1596 // stack guard check to enable interrupts.
1617 __ bind(&stack_check); 1597 __ bind(&stack_check);
1618 Label ok; 1598 Label ok;
1619 ExternalReference stack_limit = 1599 ExternalReference stack_limit =
1620 ExternalReference::address_of_stack_limit(masm->isolate()); 1600 ExternalReference::address_of_stack_limit(masm->isolate());
1621 __ cmp(esp, Operand::StaticVariable(stack_limit)); 1601 __ cmp(esp, Operand::StaticVariable(stack_limit));
1622 __ j(above_equal, &ok, Label::kNear); 1602 __ j(above_equal, &ok, Label::kNear);
1623 StackCheckStub stub; 1603 StackCheckStub stub;
1624 __ TailCallStub(&stub); 1604 __ TailCallStub(&stub);
1625 if (FLAG_debug_code) { 1605 __ Abort("Unreachable code: returned from tail call.");
1626 __ Abort("Unreachable code: returned from tail call.");
1627 }
1628 __ bind(&ok); 1606 __ bind(&ok);
1629 __ ret(0); 1607 __ ret(0);
1630 1608
1631 __ bind(&skip); 1609 __ bind(&skip);
1632 // Untag the AST id and push it on the stack. 1610 // Untag the AST id and push it on the stack.
1633 __ SmiUntag(eax); 1611 __ SmiUntag(eax);
1634 __ push(eax); 1612 __ push(eax);
1635 1613
1636 // Generate the code for doing the frame-to-frame translation using 1614 // Generate the code for doing the frame-to-frame translation using
1637 // the deoptimizer infrastructure. 1615 // the deoptimizer infrastructure.
1638 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); 1616 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1639 generator.Generate(); 1617 generator.Generate();
1640 } 1618 }
1641 1619
1642 1620
1643 #undef __ 1621 #undef __
1644 } 1622 }
1645 } // namespace v8::internal 1623 } // namespace v8::internal
1646 1624
1647 #endif // V8_TARGET_ARCH_IA32 1625 #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