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

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

Issue 8086021: Clean up the x86 assembler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 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
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 Register scratch = ebx; 62 Register scratch = ebx;
63 __ pop(scratch); // Save return address. 63 __ pop(scratch); // Save return address.
64 __ push(edi); 64 __ push(edi);
65 __ push(scratch); // Restore return address. 65 __ push(scratch); // Restore return address.
66 } else { 66 } else {
67 ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 67 ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
68 } 68 }
69 69
70 // JumpToExternalReference expects eax to contain the number of arguments 70 // JumpToExternalReference expects eax to contain the number of arguments
71 // including the receiver and the extra arguments. 71 // including the receiver and the extra arguments.
72 __ add(Operand(eax), Immediate(num_extra_args + 1)); 72 __ add(eax, Immediate(num_extra_args + 1));
73 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 73 __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
74 } 74 }
75 75
76 76
77 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { 77 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
78 // ----------- S t a t e ------------- 78 // ----------- S t a t e -------------
79 // -- eax: number of arguments 79 // -- eax: number of arguments
80 // -- edi: constructor function 80 // -- edi: constructor function
81 // ----------------------------------- 81 // -----------------------------------
82 82
83 Label slow, non_function_call; 83 Label slow, non_function_call;
84 // Check that function is not a smi. 84 // Check that function is not a smi.
85 __ JumpIfSmi(edi, &non_function_call); 85 __ JumpIfSmi(edi, &non_function_call);
86 // Check that function is a JSFunction. 86 // Check that function is a JSFunction.
87 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 87 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
88 __ j(not_equal, &slow); 88 __ j(not_equal, &slow);
89 89
90 // Jump to the function-specific construct stub. 90 // Jump to the function-specific construct stub.
91 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 91 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
92 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); 92 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset));
93 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 93 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize));
94 __ jmp(Operand(ebx)); 94 __ jmp(ebx);
95 95
96 // edi: called object 96 // edi: called object
97 // eax: number of arguments 97 // eax: number of arguments
98 // ecx: object map 98 // ecx: object map
99 Label do_call; 99 Label do_call;
100 __ bind(&slow); 100 __ bind(&slow);
101 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 101 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
102 __ j(not_equal, &non_function_call); 102 __ j(not_equal, &non_function_call);
103 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 103 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
104 __ jmp(&do_call); 104 __ jmp(&do_call);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 // edi: start of next object 206 // edi: start of next object
207 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 207 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
208 __ mov(edx, factory->undefined_value()); 208 __ mov(edx, factory->undefined_value());
209 if (count_constructions) { 209 if (count_constructions) {
210 __ movzx_b(esi, 210 __ movzx_b(esi,
211 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 211 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
212 __ lea(esi, 212 __ lea(esi,
213 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 213 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
214 // esi: offset of first field after pre-allocated fields 214 // esi: offset of first field after pre-allocated fields
215 if (FLAG_debug_code) { 215 if (FLAG_debug_code) {
216 __ cmp(esi, Operand(edi)); 216 __ cmp(esi, edi);
217 __ Assert(less_equal, 217 __ Assert(less_equal,
218 "Unexpected number of pre-allocated property fields."); 218 "Unexpected number of pre-allocated property fields.");
219 } 219 }
220 __ InitializeFieldsWithFiller(ecx, esi, edx); 220 __ InitializeFieldsWithFiller(ecx, esi, edx);
221 __ mov(edx, factory->one_pointer_filler_map()); 221 __ mov(edx, factory->one_pointer_filler_map());
222 } 222 }
223 __ InitializeFieldsWithFiller(ecx, edi, edx); 223 __ InitializeFieldsWithFiller(ecx, edi, edx);
224 224
225 // Add the object tag to make the JSObject real, so that we can continue 225 // Add the object tag to make the JSObject real, so that we can continue
226 // and jump into the continuation code at any time from now on. Any 226 // and jump into the continuation code at any time from now on. Any
227 // failures need to undo the allocation, so that the heap is in a 227 // failures need to undo the allocation, so that the heap is in a
228 // consistent state and verifiable. 228 // consistent state and verifiable.
229 // eax: initial map 229 // eax: initial map
230 // ebx: JSObject 230 // ebx: JSObject
231 // edi: start of next object 231 // edi: start of next object
232 __ or_(Operand(ebx), Immediate(kHeapObjectTag)); 232 __ or_(ebx, Immediate(kHeapObjectTag));
233 233
234 // Check if a non-empty properties array is needed. 234 // Check if a non-empty properties array is needed.
235 // Allocate and initialize a FixedArray if it is. 235 // Allocate and initialize a FixedArray if it is.
236 // eax: initial map 236 // eax: initial map
237 // ebx: JSObject 237 // ebx: JSObject
238 // edi: start of next object 238 // edi: start of next object
239 // Calculate the total number of properties described by the map. 239 // Calculate the total number of properties described by the map.
240 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); 240 __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
241 __ movzx_b(ecx, 241 __ movzx_b(ecx,
242 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 242 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
243 __ add(edx, Operand(ecx)); 243 __ add(edx, ecx);
244 // Calculate unused properties past the end of the in-object properties. 244 // Calculate unused properties past the end of the in-object properties.
245 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset)); 245 __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
246 __ sub(edx, Operand(ecx)); 246 __ sub(edx, ecx);
247 // Done if no extra properties are to be allocated. 247 // Done if no extra properties are to be allocated.
248 __ j(zero, &allocated); 248 __ j(zero, &allocated);
249 __ Assert(positive, "Property allocation count failed."); 249 __ Assert(positive, "Property allocation count failed.");
250 250
251 // Scale the number of elements by pointer size and add the header for 251 // Scale the number of elements by pointer size and add the header for
252 // FixedArrays to the start of the next object calculation from above. 252 // FixedArrays to the start of the next object calculation from above.
253 // ebx: JSObject 253 // ebx: JSObject
254 // edi: start of next object (will be start of FixedArray) 254 // edi: start of next object (will be start of FixedArray)
255 // edx: number of elements in properties array 255 // edx: number of elements in properties array
256 __ AllocateInNewSpace(FixedArray::kHeaderSize, 256 __ AllocateInNewSpace(FixedArray::kHeaderSize,
(...skipping 18 matching lines...) Expand all
275 // Initialize the fields to undefined. 275 // Initialize the fields to undefined.
276 // ebx: JSObject 276 // ebx: JSObject
277 // edi: FixedArray 277 // edi: FixedArray
278 // ecx: start of next object 278 // ecx: start of next object
279 { Label loop, entry; 279 { Label loop, entry;
280 __ mov(edx, factory->undefined_value()); 280 __ mov(edx, factory->undefined_value());
281 __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); 281 __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
282 __ jmp(&entry); 282 __ jmp(&entry);
283 __ bind(&loop); 283 __ bind(&loop);
284 __ mov(Operand(eax, 0), edx); 284 __ mov(Operand(eax, 0), edx);
285 __ add(Operand(eax), Immediate(kPointerSize)); 285 __ add(eax, Immediate(kPointerSize));
286 __ bind(&entry); 286 __ bind(&entry);
287 __ cmp(eax, Operand(ecx)); 287 __ cmp(eax, ecx);
288 __ j(below, &loop); 288 __ j(below, &loop);
289 } 289 }
290 290
291 // Store the initialized FixedArray into the properties field of 291 // Store the initialized FixedArray into the properties field of
292 // the JSObject 292 // the JSObject
293 // ebx: JSObject 293 // ebx: JSObject
294 // edi: FixedArray 294 // edi: FixedArray
295 __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag 295 __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag
296 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi); 296 __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
297 297
298 298
299 // Continue with JSObject being successfully allocated 299 // Continue with JSObject being successfully allocated
300 // ebx: JSObject 300 // ebx: JSObject
301 __ jmp(&allocated); 301 __ jmp(&allocated);
302 302
303 // Undo the setting of the new top so that the heap is verifiable. For 303 // Undo the setting of the new top so that the heap is verifiable. For
304 // example, the map's unused properties potentially do not match the 304 // example, the map's unused properties potentially do not match the
305 // allocated objects unused properties. 305 // allocated objects unused properties.
306 // ebx: JSObject (previous new top) 306 // ebx: JSObject (previous new top)
307 __ bind(&undo_allocation); 307 __ bind(&undo_allocation);
308 __ UndoAllocationInNewSpace(ebx); 308 __ UndoAllocationInNewSpace(ebx);
309 } 309 }
310 310
311 // Allocate the new receiver object using the runtime call. 311 // Allocate the new receiver object using the runtime call.
312 __ bind(&rt_call); 312 __ bind(&rt_call);
313 // Must restore edi (constructor) before calling runtime. 313 // Must restore edi (constructor) before calling runtime.
314 __ mov(edi, Operand(esp, 0)); 314 __ mov(edi, Operand(esp, 0));
315 // edi: function (constructor) 315 // edi: function (constructor)
316 __ push(edi); 316 __ push(edi);
317 __ CallRuntime(Runtime::kNewObject, 1); 317 __ CallRuntime(Runtime::kNewObject, 1);
318 __ mov(ebx, Operand(eax)); // store result in ebx 318 __ mov(ebx, eax); // store result in ebx
319 319
320 // New object allocated. 320 // New object allocated.
321 // ebx: newly allocated object 321 // ebx: newly allocated object
322 __ bind(&allocated); 322 __ bind(&allocated);
323 // Retrieve the function from the stack. 323 // Retrieve the function from the stack.
324 __ pop(edi); 324 __ pop(edi);
325 325
326 // Retrieve smi-tagged arguments count from the stack. 326 // Retrieve smi-tagged arguments count from the stack.
327 __ mov(eax, Operand(esp, 0)); 327 __ mov(eax, Operand(esp, 0));
328 __ SmiUntag(eax); 328 __ SmiUntag(eax);
329 329
330 // Push the allocated receiver to the stack. We need two copies 330 // Push the allocated receiver to the stack. We need two copies
331 // because we may have to return the original one and the calling 331 // because we may have to return the original one and the calling
332 // conventions dictate that the called function pops the receiver. 332 // conventions dictate that the called function pops the receiver.
333 __ push(ebx); 333 __ push(ebx);
334 __ push(ebx); 334 __ push(ebx);
335 335
336 // Setup pointer to last argument. 336 // Setup pointer to last argument.
337 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 337 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
338 338
339 // Copy arguments and receiver to the expression stack. 339 // Copy arguments and receiver to the expression stack.
340 Label loop, entry; 340 Label loop, entry;
341 __ mov(ecx, Operand(eax)); 341 __ mov(ecx, eax);
342 __ jmp(&entry); 342 __ jmp(&entry);
343 __ bind(&loop); 343 __ bind(&loop);
344 __ push(Operand(ebx, ecx, times_4, 0)); 344 __ push(Operand(ebx, ecx, times_4, 0));
345 __ bind(&entry); 345 __ bind(&entry);
346 __ dec(ecx); 346 __ dec(ecx);
347 __ j(greater_equal, &loop); 347 __ j(greater_equal, &loop);
348 348
349 // Call the function. 349 // Call the function.
350 if (is_api_function) { 350 if (is_api_function) {
351 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 351 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 436 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
437 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 437 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
438 438
439 // Copy arguments to the stack in a loop. 439 // Copy arguments to the stack in a loop.
440 Label loop, entry; 440 Label loop, entry;
441 __ Set(ecx, Immediate(0)); 441 __ Set(ecx, Immediate(0));
442 __ jmp(&entry); 442 __ jmp(&entry);
443 __ bind(&loop); 443 __ bind(&loop);
444 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 444 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv
445 __ push(Operand(edx, 0)); // dereference handle 445 __ push(Operand(edx, 0)); // dereference handle
446 __ inc(Operand(ecx)); 446 __ inc(ecx);
447 __ bind(&entry); 447 __ bind(&entry);
448 __ cmp(ecx, Operand(eax)); 448 __ cmp(ecx, eax);
449 __ j(not_equal, &loop); 449 __ j(not_equal, &loop);
450 450
451 // Get the function from the stack and call it. 451 // Get the function from the stack and call it.
452 // kPointerSize for the receiver. 452 // kPointerSize for the receiver.
453 __ mov(edi, Operand(esp, eax, times_4, kPointerSize)); 453 __ mov(edi, Operand(esp, eax, times_4, kPointerSize));
454 454
455 // Invoke the code. 455 // Invoke the code.
456 if (is_construct) { 456 if (is_construct) {
457 __ call(masm->isolate()->builtins()->JSConstructCall(), 457 __ call(masm->isolate()->builtins()->JSConstructCall(),
458 RelocInfo::CODE_TARGET); 458 RelocInfo::CODE_TARGET);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 // Restore call kind information. 495 // Restore call kind information.
496 __ pop(ecx); 496 __ pop(ecx);
497 // Restore receiver. 497 // Restore receiver.
498 __ pop(edi); 498 __ pop(edi);
499 499
500 // Tear down internal frame. 500 // Tear down internal frame.
501 } 501 }
502 502
503 // Do a tail-call of the compiled function. 503 // Do a tail-call of the compiled function.
504 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 504 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
505 __ jmp(Operand(eax)); 505 __ jmp(eax);
506 } 506 }
507 507
508 508
509 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 509 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
510 { 510 {
511 FrameScope scope(masm, StackFrame::INTERNAL); 511 FrameScope scope(masm, StackFrame::INTERNAL);
512 512
513 // Push a copy of the function onto the stack. 513 // Push a copy of the function onto the stack.
514 __ push(edi); 514 __ push(edi);
515 // Push call kind information. 515 // Push call kind information.
516 __ push(ecx); 516 __ push(ecx);
517 517
518 __ push(edi); // Function is also the parameter to the runtime call. 518 __ push(edi); // Function is also the parameter to the runtime call.
519 __ CallRuntime(Runtime::kLazyRecompile, 1); 519 __ CallRuntime(Runtime::kLazyRecompile, 1);
520 520
521 // Restore call kind information. 521 // Restore call kind information.
522 __ pop(ecx); 522 __ pop(ecx);
523 // Restore receiver. 523 // Restore receiver.
524 __ pop(edi); 524 __ pop(edi);
525 525
526 // Tear down internal frame. 526 // Tear down internal frame.
527 } 527 }
528 528
529 // Do a tail-call of the compiled function. 529 // Do a tail-call of the compiled function.
530 __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 530 __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
531 __ jmp(Operand(eax)); 531 __ jmp(eax);
532 } 532 }
533 533
534 534
535 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 535 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
536 Deoptimizer::BailoutType type) { 536 Deoptimizer::BailoutType type) {
537 { 537 {
538 FrameScope scope(masm, StackFrame::INTERNAL); 538 FrameScope scope(masm, StackFrame::INTERNAL);
539 539
540 // Pass the function and deoptimization type to the runtime system. 540 // Pass the function and deoptimization type to the runtime system.
541 __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 541 __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 __ popad(); 590 __ popad();
591 __ ret(0); 591 __ ret(0);
592 } 592 }
593 593
594 594
595 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 595 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
596 Factory* factory = masm->isolate()->factory(); 596 Factory* factory = masm->isolate()->factory();
597 597
598 // 1. Make sure we have at least one argument. 598 // 1. Make sure we have at least one argument.
599 { Label done; 599 { Label done;
600 __ test(eax, Operand(eax)); 600 __ test(eax, eax);
601 __ j(not_zero, &done); 601 __ j(not_zero, &done);
602 __ pop(ebx); 602 __ pop(ebx);
603 __ push(Immediate(factory->undefined_value())); 603 __ push(Immediate(factory->undefined_value()));
604 __ push(ebx); 604 __ push(ebx);
605 __ inc(eax); 605 __ inc(eax);
606 __ bind(&done); 606 __ bind(&done);
607 } 607 }
608 608
609 // 2. Get the function to call (passed as receiver) from the stack, check 609 // 2. Get the function to call (passed as receiver) from the stack, check
610 // if it is a function. 610 // if it is a function.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); 709 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
710 __ dec(ecx); 710 __ dec(ecx);
711 __ j(not_sign, &loop); // While non-negative (to copy return address). 711 __ j(not_sign, &loop); // While non-negative (to copy return address).
712 __ pop(ebx); // Discard copy of return address. 712 __ pop(ebx); // Discard copy of return address.
713 __ dec(eax); // One fewer argument (first argument is new receiver). 713 __ dec(eax); // One fewer argument (first argument is new receiver).
714 } 714 }
715 715
716 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 716 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
717 // or a function proxy via CALL_FUNCTION_PROXY. 717 // or a function proxy via CALL_FUNCTION_PROXY.
718 { Label function, non_proxy; 718 { Label function, non_proxy;
719 __ test(edx, Operand(edx)); 719 __ test(edx, edx);
720 __ j(zero, &function); 720 __ j(zero, &function);
721 __ Set(ebx, Immediate(0)); 721 __ Set(ebx, Immediate(0));
722 __ SetCallKind(ecx, CALL_AS_METHOD); 722 __ SetCallKind(ecx, CALL_AS_METHOD);
723 __ cmp(Operand(edx), Immediate(1)); 723 __ cmp(edx, Immediate(1));
724 __ j(not_equal, &non_proxy); 724 __ j(not_equal, &non_proxy);
725 725
726 __ pop(edx); // return address 726 __ pop(edx); // return address
727 __ push(edi); // re-add proxy object as additional argument 727 __ push(edi); // re-add proxy object as additional argument
728 __ push(edx); 728 __ push(edx);
729 __ inc(eax); 729 __ inc(eax);
730 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 730 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
731 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 731 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
732 RelocInfo::CODE_TARGET); 732 RelocInfo::CODE_TARGET);
733 733
734 __ bind(&non_proxy); 734 __ bind(&non_proxy);
735 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 735 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
736 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 736 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
737 RelocInfo::CODE_TARGET); 737 RelocInfo::CODE_TARGET);
738 __ bind(&function); 738 __ bind(&function);
739 } 739 }
740 740
741 // 5b. Get the code to call from the function and check that the number of 741 // 5b. Get the code to call from the function and check that the number of
742 // expected arguments matches what we're providing. If so, jump 742 // expected arguments matches what we're providing. If so, jump
743 // (tail-call) to the code in register edx without checking arguments. 743 // (tail-call) to the code in register edx without checking arguments.
744 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 744 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
745 __ mov(ebx, 745 __ mov(ebx,
746 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 746 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
747 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 747 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
748 __ SmiUntag(ebx); 748 __ SmiUntag(ebx);
749 __ SetCallKind(ecx, CALL_AS_METHOD); 749 __ SetCallKind(ecx, CALL_AS_METHOD);
750 __ cmp(eax, Operand(ebx)); 750 __ cmp(eax, ebx);
751 __ j(not_equal, 751 __ j(not_equal,
752 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); 752 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
753 753
754 ParameterCount expected(0); 754 ParameterCount expected(0);
755 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION, 755 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(),
756 NullCallWrapper(), CALL_AS_METHOD); 756 CALL_AS_METHOD);
757 } 757 }
758 758
759 759
760 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 760 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
761 static const int kArgumentsOffset = 2 * kPointerSize; 761 static const int kArgumentsOffset = 2 * kPointerSize;
762 static const int kReceiverOffset = 3 * kPointerSize; 762 static const int kReceiverOffset = 3 * kPointerSize;
763 static const int kFunctionOffset = 4 * kPointerSize; 763 static const int kFunctionOffset = 4 * kPointerSize;
764 { 764 {
765 FrameScope frame_scope(masm, StackFrame::INTERNAL); 765 FrameScope frame_scope(masm, StackFrame::INTERNAL);
766 766
767 __ push(Operand(ebp, kFunctionOffset)); // push this 767 __ push(Operand(ebp, kFunctionOffset)); // push this
768 __ push(Operand(ebp, kArgumentsOffset)); // push arguments 768 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
769 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 769 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
770 770
771 // Check the stack for overflow. We are not trying to catch 771 // Check the stack for overflow. We are not trying to catch
772 // interruptions (e.g. debug break and preemption) here, so the "real stack 772 // interruptions (e.g. debug break and preemption) here, so the "real stack
773 // limit" is checked. 773 // limit" is checked.
774 Label okay; 774 Label okay;
775 ExternalReference real_stack_limit = 775 ExternalReference real_stack_limit =
776 ExternalReference::address_of_real_stack_limit(masm->isolate()); 776 ExternalReference::address_of_real_stack_limit(masm->isolate());
777 __ mov(edi, Operand::StaticVariable(real_stack_limit)); 777 __ mov(edi, Operand::StaticVariable(real_stack_limit));
778 // Make ecx the space we have left. The stack might already be overflowed 778 // Make ecx the space we have left. The stack might already be overflowed
779 // here which will cause ecx to become negative. 779 // here which will cause ecx to become negative.
780 __ mov(ecx, Operand(esp)); 780 __ mov(ecx, esp);
781 __ sub(ecx, Operand(edi)); 781 __ sub(ecx, edi);
782 // Make edx the space we need for the array when it is unrolled onto the 782 // Make edx the space we need for the array when it is unrolled onto the
783 // stack. 783 // stack.
784 __ mov(edx, Operand(eax)); 784 __ mov(edx, eax);
785 __ shl(edx, kPointerSizeLog2 - kSmiTagSize); 785 __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
786 // Check if the arguments will overflow the stack. 786 // Check if the arguments will overflow the stack.
787 __ cmp(ecx, Operand(edx)); 787 __ cmp(ecx, edx);
788 __ j(greater, &okay); // Signed comparison. 788 __ j(greater, &okay); // Signed comparison.
789 789
790 // Out of stack space. 790 // Out of stack space.
791 __ push(Operand(ebp, 4 * kPointerSize)); // push this 791 __ push(Operand(ebp, 4 * kPointerSize)); // push this
792 __ push(eax); 792 __ push(eax);
793 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 793 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
794 __ bind(&okay); 794 __ bind(&okay);
795 // End of stack check. 795 // End of stack check.
796 796
797 // Push current index and limit. 797 // Push current index and limit.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 __ j(equal, &use_global_receiver); 836 __ j(equal, &use_global_receiver);
837 __ cmp(ebx, factory->undefined_value()); 837 __ cmp(ebx, factory->undefined_value());
838 __ j(equal, &use_global_receiver); 838 __ j(equal, &use_global_receiver);
839 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 839 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
840 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 840 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
841 __ j(above_equal, &push_receiver); 841 __ j(above_equal, &push_receiver);
842 842
843 __ bind(&call_to_object); 843 __ bind(&call_to_object);
844 __ push(ebx); 844 __ push(ebx);
845 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 845 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
846 __ mov(ebx, Operand(eax)); 846 __ mov(ebx, eax);
847 __ jmp(&push_receiver); 847 __ jmp(&push_receiver);
848 848
849 // Use the current global receiver object as the receiver. 849 // Use the current global receiver object as the receiver.
850 __ bind(&use_global_receiver); 850 __ bind(&use_global_receiver);
851 const int kGlobalOffset = 851 const int kGlobalOffset =
852 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 852 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
853 __ mov(ebx, FieldOperand(esi, kGlobalOffset)); 853 __ mov(ebx, FieldOperand(esi, kGlobalOffset));
854 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset)); 854 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset));
855 __ mov(ebx, FieldOperand(ebx, kGlobalOffset)); 855 __ mov(ebx, FieldOperand(ebx, kGlobalOffset));
856 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 856 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
(...skipping 15 matching lines...) Expand all
872 // It is important that we do not have a test instruction after the 872 // It is important that we do not have a test instruction after the
873 // call. A test instruction after the call is used to indicate that 873 // call. A test instruction after the call is used to indicate that
874 // we have generated an inline version of the keyed load. In this 874 // we have generated an inline version of the keyed load. In this
875 // case, we know that we are not generating a test instruction next. 875 // case, we know that we are not generating a test instruction next.
876 876
877 // Push the nth argument. 877 // Push the nth argument.
878 __ push(eax); 878 __ push(eax);
879 879
880 // Update the index on the stack and in register eax. 880 // Update the index on the stack and in register eax.
881 __ mov(eax, Operand(ebp, kIndexOffset)); 881 __ mov(eax, Operand(ebp, kIndexOffset));
882 __ add(Operand(eax), Immediate(1 << kSmiTagSize)); 882 __ add(eax, Immediate(1 << kSmiTagSize));
883 __ mov(Operand(ebp, kIndexOffset), eax); 883 __ mov(Operand(ebp, kIndexOffset), eax);
884 884
885 __ bind(&entry); 885 __ bind(&entry);
886 __ cmp(eax, Operand(ebp, kLimitOffset)); 886 __ cmp(eax, Operand(ebp, kLimitOffset));
887 __ j(not_equal, &loop); 887 __ j(not_equal, &loop);
888 888
889 // Invoke the function. 889 // Invoke the function.
890 Label call_proxy; 890 Label call_proxy;
891 ParameterCount actual(eax); 891 ParameterCount actual(eax);
892 __ SmiUntag(eax); 892 __ SmiUntag(eax);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 for (int i = 0; i < initial_capacity; i++) { 998 for (int i = 0; i < initial_capacity; i++) {
999 __ mov(FieldOperand(scratch1, 999 __ mov(FieldOperand(scratch1,
1000 FixedArray::kHeaderSize + i * kPointerSize), 1000 FixedArray::kHeaderSize + i * kPointerSize),
1001 scratch3); 1001 scratch3);
1002 } 1002 }
1003 } else { 1003 } else {
1004 Label loop, entry; 1004 Label loop, entry;
1005 __ jmp(&entry); 1005 __ jmp(&entry);
1006 __ bind(&loop); 1006 __ bind(&loop);
1007 __ mov(Operand(scratch1, 0), factory->the_hole_value()); 1007 __ mov(Operand(scratch1, 0), factory->the_hole_value());
1008 __ add(Operand(scratch1), Immediate(kPointerSize)); 1008 __ add(scratch1, Immediate(kPointerSize));
1009 __ bind(&entry); 1009 __ bind(&entry);
1010 __ cmp(scratch1, Operand(scratch2)); 1010 __ cmp(scratch1, scratch2);
1011 __ j(below, &loop); 1011 __ j(below, &loop);
1012 } 1012 }
1013 } 1013 }
1014 1014
1015 1015
1016 // Allocate a JSArray with the number of elements stored in a register. The 1016 // Allocate a JSArray with the number of elements stored in a register. The
1017 // register array_function holds the built-in Array function and the register 1017 // register array_function holds the built-in Array function and the register
1018 // array_size holds the size of the array as a smi. The allocated array is put 1018 // array_size holds the size of the array as a smi. The allocated array is put
1019 // into the result register and beginning and end of the FixedArray elements 1019 // into the result register and beginning and end of the FixedArray elements
1020 // storage is put into registers elements_array and elements_array_end (see 1020 // storage is put into registers elements_array and elements_array_end (see
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 // words. 1097 // words.
1098 const int kRepStosThreshold = 16; 1098 const int kRepStosThreshold = 16;
1099 Label loop, entry, done; 1099 Label loop, entry, done;
1100 __ cmp(ecx, kRepStosThreshold); 1100 __ cmp(ecx, kRepStosThreshold);
1101 __ j(below, &loop); // Note: ecx > 0. 1101 __ j(below, &loop); // Note: ecx > 0.
1102 __ rep_stos(); 1102 __ rep_stos();
1103 __ jmp(&done); 1103 __ jmp(&done);
1104 __ bind(&loop); 1104 __ bind(&loop);
1105 __ stos(); 1105 __ stos();
1106 __ bind(&entry); 1106 __ bind(&entry);
1107 __ cmp(edi, Operand(elements_array_end)); 1107 __ cmp(edi, elements_array_end);
1108 __ j(below, &loop); 1108 __ j(below, &loop);
1109 __ bind(&done); 1109 __ bind(&done);
1110 } 1110 }
1111 } 1111 }
1112 1112
1113 1113
1114 // Create a new array for the built-in Array function. This function allocates 1114 // Create a new array for the built-in Array function. This function allocates
1115 // the JSArray object and the FixedArray elements array and initializes these. 1115 // the JSArray object and the FixedArray elements array and initializes these.
1116 // If the Array cannot be constructed in native code the runtime is called. This 1116 // If the Array cannot be constructed in native code the runtime is called. This
1117 // function assumes the following state: 1117 // function assumes the following state:
(...skipping 17 matching lines...) Expand all
1135 // be no garbage collection with this on the stack. 1135 // be no garbage collection with this on the stack.
1136 int push_count = 0; 1136 int push_count = 0;
1137 if (construct_call) { 1137 if (construct_call) {
1138 push_count++; 1138 push_count++;
1139 __ push(edi); 1139 __ push(edi);
1140 } 1140 }
1141 push_count++; 1141 push_count++;
1142 __ push(eax); 1142 __ push(eax);
1143 1143
1144 // Check for array construction with zero arguments. 1144 // Check for array construction with zero arguments.
1145 __ test(eax, Operand(eax)); 1145 __ test(eax, eax);
1146 __ j(not_zero, &argc_one_or_more); 1146 __ j(not_zero, &argc_one_or_more);
1147 1147
1148 __ bind(&empty_array); 1148 __ bind(&empty_array);
1149 // Handle construction of an empty array. 1149 // Handle construction of an empty array.
1150 AllocateEmptyJSArray(masm, 1150 AllocateEmptyJSArray(masm,
1151 edi, 1151 edi,
1152 eax, 1152 eax,
1153 ebx, 1153 ebx,
1154 ecx, 1154 ecx,
1155 edi, 1155 edi,
1156 kPreallocatedArrayElements, 1156 kPreallocatedArrayElements,
1157 &prepare_generic_code_call); 1157 &prepare_generic_code_call);
1158 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); 1158 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1);
1159 __ pop(ebx); 1159 __ pop(ebx);
1160 if (construct_call) { 1160 if (construct_call) {
1161 __ pop(edi); 1161 __ pop(edi);
1162 } 1162 }
1163 __ ret(kPointerSize); 1163 __ ret(kPointerSize);
1164 1164
1165 // Check for one argument. Bail out if argument is not smi or if it is 1165 // Check for one argument. Bail out if argument is not smi or if it is
1166 // negative. 1166 // negative.
1167 __ bind(&argc_one_or_more); 1167 __ bind(&argc_one_or_more);
1168 __ cmp(eax, 1); 1168 __ cmp(eax, 1);
1169 __ j(not_equal, &argc_two_or_more); 1169 __ j(not_equal, &argc_two_or_more);
1170 STATIC_ASSERT(kSmiTag == 0); 1170 STATIC_ASSERT(kSmiTag == 0);
1171 __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize)); 1171 __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize));
1172 __ test(ecx, Operand(ecx)); 1172 __ test(ecx, ecx);
1173 __ j(not_zero, &not_empty_array); 1173 __ j(not_zero, &not_empty_array);
1174 1174
1175 // The single argument passed is zero, so we jump to the code above used to 1175 // The single argument passed is zero, so we jump to the code above used to
1176 // handle the case of no arguments passed. To adapt the stack for that we move 1176 // handle the case of no arguments passed. To adapt the stack for that we move
1177 // the return address and the pushed constructor (if pushed) one stack slot up 1177 // the return address and the pushed constructor (if pushed) one stack slot up
1178 // thereby removing the passed argument. Argc is also on the stack - at the 1178 // thereby removing the passed argument. Argc is also on the stack - at the
1179 // bottom - and it needs to be changed from 1 to 0 to have the call into the 1179 // bottom - and it needs to be changed from 1 to 0 to have the call into the
1180 // runtime system work in case a GC is required. 1180 // runtime system work in case a GC is required.
1181 for (int i = push_count; i > 0; i--) { 1181 for (int i = push_count; i > 0; i--) {
1182 __ mov(eax, Operand(esp, i * kPointerSize)); 1182 __ mov(eax, Operand(esp, i * kPointerSize));
1183 __ mov(Operand(esp, (i + 1) * kPointerSize), eax); 1183 __ mov(Operand(esp, (i + 1) * kPointerSize), eax);
1184 } 1184 }
1185 __ add(Operand(esp), Immediate(2 * kPointerSize)); // Drop two stack slots. 1185 __ add(esp, Immediate(2 * kPointerSize)); // Drop two stack slots.
1186 __ push(Immediate(0)); // Treat this as a call with argc of zero. 1186 __ push(Immediate(0)); // Treat this as a call with argc of zero.
1187 __ jmp(&empty_array); 1187 __ jmp(&empty_array);
1188 1188
1189 __ bind(&not_empty_array); 1189 __ bind(&not_empty_array);
1190 __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask)); 1190 __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask));
1191 __ j(not_zero, &prepare_generic_code_call); 1191 __ j(not_zero, &prepare_generic_code_call);
1192 1192
1193 // Handle construction of an empty array of a certain size. Get the size from 1193 // Handle construction of an empty array of a certain size. Get the size from
1194 // the stack and bail out if size is to large to actually allocate an elements 1194 // the stack and bail out if size is to large to actually allocate an elements
1195 // array. 1195 // array.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 // edi: location of the last argument 1265 // edi: location of the last argument
1266 // esp[0]: JSArray 1266 // esp[0]: JSArray
1267 // esp[4]: return address 1267 // esp[4]: return address
1268 // esp[8]: last argument 1268 // esp[8]: last argument
1269 Label loop, entry; 1269 Label loop, entry;
1270 __ mov(ecx, ebx); 1270 __ mov(ecx, ebx);
1271 __ jmp(&entry); 1271 __ jmp(&entry);
1272 __ bind(&loop); 1272 __ bind(&loop);
1273 __ mov(eax, Operand(edi, ecx, times_pointer_size, 0)); 1273 __ mov(eax, Operand(edi, ecx, times_pointer_size, 0));
1274 __ mov(Operand(edx, 0), eax); 1274 __ mov(Operand(edx, 0), eax);
1275 __ add(Operand(edx), Immediate(kPointerSize)); 1275 __ add(edx, Immediate(kPointerSize));
1276 __ bind(&entry); 1276 __ bind(&entry);
1277 __ dec(ecx); 1277 __ dec(ecx);
1278 __ j(greater_equal, &loop); 1278 __ j(greater_equal, &loop);
1279 1279
1280 // Remove caller arguments from the stack and return. 1280 // Remove caller arguments from the stack and return.
1281 // ebx: argc 1281 // ebx: argc
1282 // esp[0]: JSArray 1282 // esp[0]: JSArray
1283 // esp[4]: return address 1283 // esp[4]: return address
1284 // esp[8]: last argument 1284 // esp[8]: last argument
1285 __ pop(eax); 1285 __ pop(eax);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 // -- edi : constructor function 1371 // -- edi : constructor function
1372 // -- esp[0] : return address 1372 // -- esp[0] : return address
1373 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1373 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1374 // -- esp[(argc + 1) * 4] : receiver 1374 // -- esp[(argc + 1) * 4] : receiver
1375 // ----------------------------------- 1375 // -----------------------------------
1376 Counters* counters = masm->isolate()->counters(); 1376 Counters* counters = masm->isolate()->counters();
1377 __ IncrementCounter(counters->string_ctor_calls(), 1); 1377 __ IncrementCounter(counters->string_ctor_calls(), 1);
1378 1378
1379 if (FLAG_debug_code) { 1379 if (FLAG_debug_code) {
1380 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); 1380 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
1381 __ cmp(edi, Operand(ecx)); 1381 __ cmp(edi, ecx);
1382 __ Assert(equal, "Unexpected String function"); 1382 __ Assert(equal, "Unexpected String function");
1383 } 1383 }
1384 1384
1385 // Load the first argument into eax and get rid of the rest 1385 // Load the first argument into eax and get rid of the rest
1386 // (including the receiver). 1386 // (including the receiver).
1387 Label no_arguments; 1387 Label no_arguments;
1388 __ test(eax, Operand(eax)); 1388 __ test(eax, eax);
1389 __ j(zero, &no_arguments); 1389 __ j(zero, &no_arguments);
1390 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1390 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1391 __ pop(ecx); 1391 __ pop(ecx);
1392 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1392 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1393 __ push(ecx); 1393 __ push(ecx);
1394 __ mov(eax, ebx); 1394 __ mov(eax, ebx);
1395 1395
1396 // Lookup the argument in the number to string cache. 1396 // Lookup the argument in the number to string cache.
1397 Label not_cached, argument_is_string; 1397 Label not_cached, argument_is_string;
1398 NumberToStringStub::GenerateLookupNumberStringCache( 1398 NumberToStringStub::GenerateLookupNumberStringCache(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 FrameScope scope(masm, StackFrame::INTERNAL); 1488 FrameScope scope(masm, StackFrame::INTERNAL);
1489 __ push(ebx); 1489 __ push(ebx);
1490 __ CallRuntime(Runtime::kNewStringWrapper, 1); 1490 __ CallRuntime(Runtime::kNewStringWrapper, 1);
1491 } 1491 }
1492 __ ret(0); 1492 __ ret(0);
1493 } 1493 }
1494 1494
1495 1495
1496 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1496 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1497 __ push(ebp); 1497 __ push(ebp);
1498 __ mov(ebp, Operand(esp)); 1498 __ mov(ebp, esp);
1499 1499
1500 // Store the arguments adaptor context sentinel. 1500 // Store the arguments adaptor context sentinel.
1501 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1501 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1502 1502
1503 // Push the function on the stack. 1503 // Push the function on the stack.
1504 __ push(edi); 1504 __ push(edi);
1505 1505
1506 // Preserve the number of arguments on the stack. Must preserve eax, 1506 // Preserve the number of arguments on the stack. Must preserve eax,
1507 // ebx and ecx because these registers are used when copying the 1507 // ebx and ecx because these registers are used when copying the
1508 // arguments and the receiver. 1508 // arguments and the receiver.
(...skipping 23 matching lines...) Expand all
1532 // -- eax : actual number of arguments 1532 // -- eax : actual number of arguments
1533 // -- ebx : expected number of arguments 1533 // -- ebx : expected number of arguments
1534 // -- ecx : call kind information 1534 // -- ecx : call kind information
1535 // -- edx : code entry to call 1535 // -- edx : code entry to call
1536 // ----------------------------------- 1536 // -----------------------------------
1537 1537
1538 Label invoke, dont_adapt_arguments; 1538 Label invoke, dont_adapt_arguments;
1539 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 1539 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1540 1540
1541 Label enough, too_few; 1541 Label enough, too_few;
1542 __ cmp(eax, Operand(ebx)); 1542 __ cmp(eax, ebx);
1543 __ j(less, &too_few); 1543 __ j(less, &too_few);
1544 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 1544 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1545 __ j(equal, &dont_adapt_arguments); 1545 __ j(equal, &dont_adapt_arguments);
1546 1546
1547 { // Enough parameters: Actual >= expected. 1547 { // Enough parameters: Actual >= expected.
1548 __ bind(&enough); 1548 __ bind(&enough);
1549 EnterArgumentsAdaptorFrame(masm); 1549 EnterArgumentsAdaptorFrame(masm);
1550 1550
1551 // Copy receiver and all expected arguments. 1551 // Copy receiver and all expected arguments.
1552 const int offset = StandardFrameConstants::kCallerSPOffset; 1552 const int offset = StandardFrameConstants::kCallerSPOffset;
1553 __ lea(eax, Operand(ebp, eax, times_4, offset)); 1553 __ lea(eax, Operand(ebp, eax, times_4, offset));
1554 __ mov(edi, -1); // account for receiver 1554 __ mov(edi, -1); // account for receiver
1555 1555
1556 Label copy; 1556 Label copy;
1557 __ bind(&copy); 1557 __ bind(&copy);
1558 __ inc(edi); 1558 __ inc(edi);
1559 __ push(Operand(eax, 0)); 1559 __ push(Operand(eax, 0));
1560 __ sub(Operand(eax), Immediate(kPointerSize)); 1560 __ sub(eax, Immediate(kPointerSize));
1561 __ cmp(edi, Operand(ebx)); 1561 __ cmp(edi, ebx);
1562 __ j(less, &copy); 1562 __ j(less, &copy);
1563 __ jmp(&invoke); 1563 __ jmp(&invoke);
1564 } 1564 }
1565 1565
1566 { // Too few parameters: Actual < expected. 1566 { // Too few parameters: Actual < expected.
1567 __ bind(&too_few); 1567 __ bind(&too_few);
1568 EnterArgumentsAdaptorFrame(masm); 1568 EnterArgumentsAdaptorFrame(masm);
1569 1569
1570 // Copy receiver and all actual arguments. 1570 // Copy receiver and all actual arguments.
1571 const int offset = StandardFrameConstants::kCallerSPOffset; 1571 const int offset = StandardFrameConstants::kCallerSPOffset;
1572 __ lea(edi, Operand(ebp, eax, times_4, offset)); 1572 __ lea(edi, Operand(ebp, eax, times_4, offset));
1573 // ebx = expected - actual. 1573 // ebx = expected - actual.
1574 __ sub(ebx, Operand(eax)); 1574 __ sub(ebx, eax);
1575 // eax = -actual - 1 1575 // eax = -actual - 1
1576 __ neg(eax); 1576 __ neg(eax);
1577 __ sub(Operand(eax), Immediate(1)); 1577 __ sub(eax, Immediate(1));
1578 1578
1579 Label copy; 1579 Label copy;
1580 __ bind(&copy); 1580 __ bind(&copy);
1581 __ inc(eax); 1581 __ inc(eax);
1582 __ push(Operand(edi, 0)); 1582 __ push(Operand(edi, 0));
1583 __ sub(Operand(edi), Immediate(kPointerSize)); 1583 __ sub(edi, Immediate(kPointerSize));
1584 __ test(eax, Operand(eax)); 1584 __ test(eax, eax);
1585 __ j(not_zero, &copy); 1585 __ j(not_zero, &copy);
1586 1586
1587 // Fill remaining expected arguments with undefined values. 1587 // Fill remaining expected arguments with undefined values.
1588 Label fill; 1588 Label fill;
1589 __ bind(&fill); 1589 __ bind(&fill);
1590 __ inc(eax); 1590 __ inc(eax);
1591 __ push(Immediate(masm->isolate()->factory()->undefined_value())); 1591 __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1592 __ cmp(eax, Operand(ebx)); 1592 __ cmp(eax, ebx);
1593 __ j(less, &fill); 1593 __ j(less, &fill);
1594 } 1594 }
1595 1595
1596 // Call the entry point. 1596 // Call the entry point.
1597 __ bind(&invoke); 1597 __ bind(&invoke);
1598 // Restore function pointer. 1598 // Restore function pointer.
1599 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1599 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1600 __ call(Operand(edx)); 1600 __ call(edx);
1601 1601
1602 // Leave frame and return. 1602 // Leave frame and return.
1603 LeaveArgumentsAdaptorFrame(masm); 1603 LeaveArgumentsAdaptorFrame(masm);
1604 __ ret(0); 1604 __ ret(0);
1605 1605
1606 // ------------------------------------------- 1606 // -------------------------------------------
1607 // Dont adapt arguments. 1607 // Dont adapt arguments.
1608 // ------------------------------------------- 1608 // -------------------------------------------
1609 __ bind(&dont_adapt_arguments); 1609 __ bind(&dont_adapt_arguments);
1610 __ jmp(Operand(edx)); 1610 __ jmp(edx);
1611 } 1611 }
1612 1612
1613 1613
1614 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1614 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1615 CpuFeatures::TryForceFeatureScope scope(SSE2); 1615 CpuFeatures::TryForceFeatureScope scope(SSE2);
1616 if (!CpuFeatures::IsSupported(SSE2) && FLAG_debug_code) { 1616 if (!CpuFeatures::IsSupported(SSE2) && FLAG_debug_code) {
1617 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); 1617 __ Abort("Unreachable code: Cannot optimize without SSE2 support.");
1618 return; 1618 return;
1619 } 1619 }
1620 1620
(...skipping 21 matching lines...) Expand all
1642 // replacement runtime function. 1642 // replacement runtime function.
1643 { 1643 {
1644 FrameScope scope(masm, StackFrame::INTERNAL); 1644 FrameScope scope(masm, StackFrame::INTERNAL);
1645 __ push(eax); 1645 __ push(eax);
1646 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1646 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1647 } 1647 }
1648 1648
1649 // If the result was -1 it means that we couldn't optimize the 1649 // If the result was -1 it means that we couldn't optimize the
1650 // function. Just return and continue in the unoptimized version. 1650 // function. Just return and continue in the unoptimized version.
1651 Label skip; 1651 Label skip;
1652 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); 1652 __ cmp(eax, Immediate(Smi::FromInt(-1)));
1653 __ j(not_equal, &skip, Label::kNear); 1653 __ j(not_equal, &skip, Label::kNear);
1654 __ ret(0); 1654 __ ret(0);
1655 1655
1656 // If we decide not to perform on-stack replacement we perform a 1656 // If we decide not to perform on-stack replacement we perform a
1657 // stack guard check to enable interrupts. 1657 // stack guard check to enable interrupts.
1658 __ bind(&stack_check); 1658 __ bind(&stack_check);
1659 Label ok; 1659 Label ok;
1660 ExternalReference stack_limit = 1660 ExternalReference stack_limit =
1661 ExternalReference::address_of_stack_limit(masm->isolate()); 1661 ExternalReference::address_of_stack_limit(masm->isolate());
1662 __ cmp(esp, Operand::StaticVariable(stack_limit)); 1662 __ cmp(esp, Operand::StaticVariable(stack_limit));
(...skipping 16 matching lines...) Expand all
1679 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); 1679 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1680 generator.Generate(); 1680 generator.Generate();
1681 } 1681 }
1682 1682
1683 1683
1684 #undef __ 1684 #undef __
1685 } 1685 }
1686 } // namespace v8::internal 1686 } // namespace v8::internal
1687 1687
1688 #endif // V8_TARGET_ARCH_IA32 1688 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698