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

Side by Side Diff: vm/code_generator_ia32.cc

Issue 10535180: Allow implicit 'close your eyes' of native methods. This will hopefully fix issue 3466. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 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 | « vm/ast.h ('k') | vm/code_generator_test.cc » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 366
367 // Input parameters: 367 // Input parameters:
368 // ESP : points to return address. 368 // ESP : points to return address.
369 // ESP + 4 : address of last argument (arg n-1). 369 // ESP + 4 : address of last argument (arg n-1).
370 // ESP + 4*n : address of first argument (arg 0). 370 // ESP + 4*n : address of first argument (arg 0).
371 // EDX : arguments descriptor array. 371 // EDX : arguments descriptor array.
372 void CodeGenerator::GenerateEntryCode() { 372 void CodeGenerator::GenerateEntryCode() {
373 const Immediate raw_null = 373 const Immediate raw_null =
374 Immediate(reinterpret_cast<intptr_t>(Object::null())); 374 Immediate(reinterpret_cast<intptr_t>(Object::null()));
375 const Function& function = parsed_function_.function(); 375 const Function& function = parsed_function_.function();
376 const bool is_instance_native_closure =
377 function.is_native() && function.IsImplicitInstanceClosureFunction();
376 378
377 // 1. Compute the frame size and enter the frame (reserving local space 379 // 1. Compute the frame size and enter the frame (reserving local space
378 // for copied incoming and default arguments and stack-allocated local 380 // for copied incoming and default arguments and stack-allocated local
379 // variables). 381 // variables).
380 // 382 //
381 // TODO(regis): We may give up reserving space on stack for args/locals 383 // TODO(regis): We may give up reserving space on stack for args/locals
382 // because pushes of initial values may be more effective than moves. 384 // because pushes of initial values may be more effective than moves.
383 LocalScope* scope = parsed_function_.node_sequence()->scope(); 385 LocalScope* scope = parsed_function_.node_sequence()->scope();
384 const int num_fixed_params = function.num_fixed_parameters(); 386 const int num_fixed_params = function.num_fixed_parameters();
385 const int num_opt_params = function.num_optional_parameters(); 387 const int num_opt_params = function.num_optional_parameters();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 436 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
435 // Check that num_args <= num_params. 437 // Check that num_args <= num_params.
436 Label wrong_num_arguments; 438 Label wrong_num_arguments;
437 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); 439 __ cmpl(EBX, Immediate(Smi::RawValue(num_params)));
438 __ j(GREATER, &wrong_num_arguments); 440 __ j(GREATER, &wrong_num_arguments);
439 // Number of positional args is the second Smi in descriptor array (EDX). 441 // Number of positional args is the second Smi in descriptor array (EDX).
440 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 442 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
441 // Check that num_pos_args >= num_fixed_params. 443 // Check that num_pos_args >= num_fixed_params.
442 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); 444 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
443 __ j(LESS, &wrong_num_arguments); 445 __ j(LESS, &wrong_num_arguments);
446
444 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. 447 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
445 // Let EBX point to the last passed positional argument, i.e. to 448 // Let EBX point to the last passed positional argument, i.e. to
446 // fp[1 + num_args - (num_pos_args - 1)]. 449 // fp[1 + num_args - (num_pos_args - 1)].
447 __ subl(EBX, ECX); 450 __ subl(EBX, ECX);
448 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); 451 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
449 // Let EDI point to the last copied positional argument, i.e. to 452 // Let EDI point to the last copied positional argument, i.e. to
450 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. 453 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
451 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; 454 int implicit_this_param_pos = is_instance_native_closure ? -1 : 0;
455 const int index =
456 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
457 // First copy captured receiver if function is an implicit native closure.
458 if (is_instance_native_closure) {
459 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0)));
460 __ movl(Address(EBP, (index * kWordSize)), EAX);
461 }
452 __ leal(EDI, Address(EBP, (index * kWordSize))); 462 __ leal(EDI, Address(EBP, (index * kWordSize)));
453 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. 463 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
454 __ subl(EDI, ECX); 464 __ subl(EDI, ECX);
455 __ SmiUntag(ECX); 465 __ SmiUntag(ECX);
456 Label loop, loop_condition; 466 Label loop, loop_condition;
457 __ jmp(&loop_condition, Assembler::kNearJump); 467 __ jmp(&loop_condition, Assembler::kNearJump);
458 // We do not use the final allocation index of the variable here, i.e. 468 // We do not use the final allocation index of the variable here, i.e.
459 // scope->VariableAt(i)->index(), because captured variables still need 469 // scope->VariableAt(i)->index(), because captured variables still need
460 // to be copied to the context that is not yet allocated. 470 // to be copied to the context that is not yet allocated.
461 const Address argument_addr(EBX, ECX, TIMES_4, 0); 471 const Address argument_addr(EBX, ECX, TIMES_4, 0);
462 const Address copy_addr(EDI, ECX, TIMES_4, 0); 472 const Address copy_addr(EDI, ECX, TIMES_4, 0);
463 __ Bind(&loop); 473 __ Bind(&loop);
464 __ movl(EAX, argument_addr); 474 __ movl(EAX, argument_addr);
465 __ movl(copy_addr, EAX); 475 __ movl(copy_addr, EAX);
466 __ Bind(&loop_condition); 476 __ Bind(&loop_condition);
467 __ decl(ECX); 477 __ decl(ECX);
468 __ j(POSITIVE, &loop, Assembler::kNearJump); 478 __ j(POSITIVE, &loop, Assembler::kNearJump);
469 479
470 // Copy or initialize optional named arguments. 480 // Copy or initialize optional named arguments.
471 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments. 481 Label all_arguments_processed;
472 // Start by alphabetically sorting the names of the optional parameters. 482 if (num_opt_params > 0) {
473 LocalVariable** opt_param = new LocalVariable*[num_opt_params]; 483 // Start by alphabetically sorting the names of the optional parameters.
474 int* opt_param_position = new int[num_opt_params]; 484 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
475 for (int pos = num_fixed_params; pos < num_params; pos++) { 485 int* opt_param_position = new int[num_opt_params];
476 LocalVariable* parameter = scope->VariableAt(pos); 486 for (int pos = num_fixed_params; pos < num_params; pos++) {
477 const String& opt_param_name = parameter->name(); 487 LocalVariable* parameter = scope->VariableAt(pos);
478 int i = pos - num_fixed_params; 488 const String& opt_param_name = parameter->name();
479 while (--i >= 0) { 489 int i = pos - num_fixed_params;
480 LocalVariable* param_i = opt_param[i]; 490 while (--i >= 0) {
481 const intptr_t result = opt_param_name.CompareTo(param_i->name()); 491 LocalVariable* param_i = opt_param[i];
482 ASSERT(result != 0); 492 const intptr_t result = opt_param_name.CompareTo(param_i->name());
483 if (result > 0) break; 493 ASSERT(result != 0);
484 opt_param[i + 1] = opt_param[i]; 494 if (result > 0) break;
485 opt_param_position[i + 1] = opt_param_position[i]; 495 opt_param[i + 1] = opt_param[i];
496 opt_param_position[i + 1] = opt_param_position[i];
497 }
498 opt_param[i + 1] = parameter;
499 opt_param_position[i + 1] = pos;
486 } 500 }
487 opt_param[i + 1] = parameter; 501 // Generate code handling each optional parameter in alphabetical order.
488 opt_param_position[i + 1] = pos; 502 // Total number of args is the first Smi in args descriptor array (EDX).
503 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
504 // Number of positional args is the second Smi in descriptor array (EDX).
505 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
506 __ SmiUntag(ECX);
507 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
508 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize));
509 // Let EDI point to the name/pos pair of the first named argument.
510 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
511 for (int i = 0; i < num_opt_params; i++) {
512 // Handle this optional parameter only if k or fewer positional args
513 // have been passed, where k is the position of this optional parameter
514 // in the formal parameter list.
515 Label load_default_value, assign_optional_parameter, next_parameter;
516 const int param_pos = opt_param_position[i];
517 __ cmpl(ECX, Immediate(param_pos));
518 __ j(GREATER, &next_parameter, Assembler::kNearJump);
519 // Check if this named parameter was passed in.
520 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the arg.
521 __ CompareObject(EAX, opt_param[i]->name());
522 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
523 // Load EAX with passed-in argument at provided arg_pos, i.e. at
524 // fp[1 + argc - arg_pos].
525 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
526 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
527 __ negl(EAX);
528 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
529 __ movl(EAX, argument_addr);
530 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
531 __ Bind(&load_default_value);
532 // Load EAX with default argument at pos.
533 const Object& value = Object::ZoneHandle(
534 parsed_function_.default_parameter_values().At(
535 param_pos - num_fixed_params));
536 __ LoadObject(EAX, value);
537 __ Bind(&assign_optional_parameter);
538 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
539 // We do not use the final allocation index of the variable here, i.e.
540 // scope->VariableAt(i)->index(), because captured variables still need
541 // to be copied to the context that is not yet allocated.
542 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
543 param_pos + implicit_this_param_pos);
544 const Address param_addr(EBP, (computed_param_pos * kWordSize));
545 __ movl(param_addr, EAX);
546 __ Bind(&next_parameter);
547 }
548 delete[] opt_param;
549 delete[] opt_param_position;
550 // Check that EDI now points to null terminator in the array descriptor.
551 __ cmpl(Address(EDI, 0), raw_null);
552 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
553 } else {
554 ASSERT(is_instance_native_closure);
555 __ jmp(&all_arguments_processed, Assembler::kNearJump);
489 } 556 }
490 // Generate code handling each optional parameter in alphabetical order.
491 // Total number of args is the first Smi in args descriptor array (EDX).
492 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
493 // Number of positional args is the second Smi in descriptor array (EDX).
494 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
495 __ SmiUntag(ECX);
496 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
497 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize));
498 // Let EDI point to the name/pos pair of the first named argument.
499 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
500 for (int i = 0; i < num_opt_params; i++) {
501 // Handle this optional parameter only if k or fewer positional arguments
502 // have been passed, where k is the position of this optional parameter in
503 // the formal parameter list.
504 Label load_default_value, assign_optional_parameter, next_parameter;
505 const int param_pos = opt_param_position[i];
506 __ cmpl(ECX, Immediate(param_pos));
507 __ j(GREATER, &next_parameter, Assembler::kNearJump);
508 // Check if this named parameter was passed in.
509 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
510 __ CompareObject(EAX, opt_param[i]->name());
511 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
512 // Load EAX with passed-in argument at provided arg_pos, i.e. at
513 // fp[1 + argc - arg_pos].
514 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
515 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
516 __ negl(EAX);
517 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
518 __ movl(EAX, argument_addr);
519 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
520 __ Bind(&load_default_value);
521 // Load EAX with default argument at pos.
522 const Object& value = Object::ZoneHandle(
523 parsed_function_.default_parameter_values().At(
524 param_pos - num_fixed_params));
525 __ LoadObject(EAX, value);
526 __ Bind(&assign_optional_parameter);
527 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
528 // We do not use the final allocation index of the variable here, i.e.
529 // scope->VariableAt(i)->index(), because captured variables still need
530 // to be copied to the context that is not yet allocated.
531 const Address param_addr(
532 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize);
533 __ movl(param_addr, EAX);
534 __ Bind(&next_parameter);
535 }
536 delete[] opt_param;
537 delete[] opt_param_position;
538 // Check that EDI now points to the null terminator in the array descriptor.
539 Label all_arguments_processed;
540 __ cmpl(Address(EDI, 0), raw_null);
541 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
542 557
543 __ Bind(&wrong_num_arguments); 558 __ Bind(&wrong_num_arguments);
544 if (locals_space_size() != 0) { 559 if (locals_space_size() != 0) {
545 // We need to unwind the space we reserved for locals and copied 560 // We need to unwind the space we reserved for locals and copied
546 // parameters. The NoSuchMethodFunction stub does not expect to 561 // parameters. The NoSuchMethodFunction stub does not expect to
547 // see that area on the stack. 562 // see that area on the stack.
548 __ addl(ESP, Immediate(locals_space_size())); 563 __ addl(ESP, Immediate(locals_space_size()));
549 } 564 }
550 if (function.IsClosureFunction()) { 565 if (function.IsClosureFunction()) {
551 GenerateCallRuntime(AstNode::kNoId, 566 GenerateCallRuntime(AstNode::kNoId,
(...skipping 2208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2760 } 2775 }
2761 // It is not necessary to generate a type test of the assigned value here, 2776 // It is not necessary to generate a type test of the assigned value here,
2762 // because the setter will check the type of its incoming arguments. 2777 // because the setter will check the type of its incoming arguments.
2763 GenerateStaticSetterCall(node->token_index(), 2778 GenerateStaticSetterCall(node->token_index(),
2764 node->cls(), 2779 node->cls(),
2765 node->field_name()); 2780 node->field_name());
2766 } 2781 }
2767 2782
2768 2783
2769 void CodeGenerator::VisitNativeBodyNode(NativeBodyNode* node) { 2784 void CodeGenerator::VisitNativeBodyNode(NativeBodyNode* node) {
2785 intptr_t argument_count = node->argument_count();
2786 if (node->is_native_instance_closure()) {
2787 argument_count += 1;
2788 }
2789
2770 // Push the result place holder initialized to NULL. 2790 // Push the result place holder initialized to NULL.
2771 __ PushObject(Object::ZoneHandle()); 2791 __ PushObject(Object::ZoneHandle());
2772 // Pass a pointer to the first argument in EAX. 2792 // Pass a pointer to the first argument in EAX.
2773 if (!node->has_optional_parameters()) { 2793 if (!node->has_optional_parameters() && !node->is_native_instance_closure()) {
2774 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); 2794 __ leal(EAX, Address(EBP, (1 + argument_count) * kWordSize));
2775 } else { 2795 } else {
2776 __ leal(EAX, 2796 __ leal(EAX,
2777 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); 2797 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize));
2778 } 2798 }
2779 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); 2799 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function())));
2780 __ movl(EDX, Immediate(node->argument_count())); 2800 __ movl(EDX, Immediate(argument_count));
2781 GenerateCall(node->token_index(), 2801 GenerateCall(node->token_index(),
2782 &StubCode::CallNativeCFunctionLabel(), 2802 &StubCode::CallNativeCFunctionLabel(),
2783 PcDescriptors::kOther); 2803 PcDescriptors::kOther);
2784 // Result is on the stack. 2804 // Result is on the stack.
2785 if (!IsResultNeeded(node)) { 2805 if (!IsResultNeeded(node)) {
2786 __ popl(EAX); 2806 __ popl(EAX);
2787 } 2807 }
2788 } 2808 }
2789 2809
2790 2810
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 const Error& error = Error::Handle( 2963 const Error& error = Error::Handle(
2944 Parser::FormatError(script, token_index, "Error", format, args)); 2964 Parser::FormatError(script, token_index, "Error", format, args));
2945 va_end(args); 2965 va_end(args);
2946 Isolate::Current()->long_jump_base()->Jump(1, error); 2966 Isolate::Current()->long_jump_base()->Jump(1, error);
2947 UNREACHABLE(); 2967 UNREACHABLE();
2948 } 2968 }
2949 2969
2950 } // namespace dart 2970 } // namespace dart
2951 2971
2952 #endif // defined TARGET_ARCH_IA32 2972 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/ast.h ('k') | vm/code_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698