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

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

Issue 7077: Under construction: Preliminary change to support per... Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 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
« no previous file with comments | « src/codegen-ia32.h ('k') | src/heap.cc » ('j') | src/objects.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 int value_; 1172 int value_;
1173 }; 1173 };
1174 1174
1175 1175
1176 void SmiComparisonDeferred::Generate() { 1176 void SmiComparisonDeferred::Generate() {
1177 CompareStub stub(cc_, strict_); 1177 CompareStub stub(cc_, strict_);
1178 // Setup parameters and call stub. 1178 // Setup parameters and call stub.
1179 __ mov(edx, Operand(eax)); 1179 __ mov(edx, Operand(eax));
1180 __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); 1180 __ mov(Operand(eax), Immediate(Smi::FromInt(value_)));
1181 __ CallStub(&stub); 1181 __ CallStub(&stub);
1182 __ cmp(eax, 0); 1182 if (cc_ == equal) {
1183 __ test(eax, Operand(eax));
1184 } else {
1185 __ cmp(eax, 0);
1186 }
1183 // "result" is returned in the flags 1187 // "result" is returned in the flags
1184 } 1188 }
1185 1189
1186 1190
1187 void CodeGenerator::SmiComparison(Condition cc, 1191 void CodeGenerator::SmiComparison(Condition cc,
1188 Handle<Object> value, 1192 Handle<Object> value,
1189 bool strict) { 1193 bool strict) {
1190 // Strict only makes sense for equality comparisons. 1194 // Strict only makes sense for equality comparisons.
1191 ASSERT(!strict || cc == equal); 1195 ASSERT(!strict || cc == equal);
1192 1196
1193 int int_value = Smi::cast(*value)->value(); 1197 int int_value = Smi::cast(*value)->value();
1194 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 1198 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
1195 1199
1196 SmiComparisonDeferred* deferred = 1200 SmiComparisonDeferred* deferred =
1197 new SmiComparisonDeferred(this, cc, strict, int_value); 1201 new SmiComparisonDeferred(this, cc, strict, int_value);
1198 __ pop(eax); 1202 __ pop(eax);
1199 __ test(eax, Immediate(kSmiTagMask)); 1203 __ test(eax, Immediate(kSmiTagMask));
1200 __ j(not_zero, deferred->enter(), not_taken); 1204 __ j(not_zero, deferred->enter(), not_taken);
1201 // Test smi equality by pointer comparison. 1205 // Test smi equality by pointer comparison.
1202 __ cmp(Operand(eax), Immediate(value)); 1206 __ cmp(Operand(eax), Immediate(value));
1203 __ bind(deferred->exit()); 1207 __ bind(deferred->exit());
1204 cc_reg_ = cc; 1208 cc_reg_ = cc;
1205 } 1209 }
1206 1210
1207 1211
1208 class CallFunctionStub: public CodeStub { 1212 class CallFunctionStub: public CodeStub {
1209 public: 1213 public:
1210 explicit CallFunctionStub(int argc) : argc_(argc) { } 1214 explicit CallFunctionStub(int argc, bool call_constructor)
1215 : argc_(argc), call_constructor_(call_constructor) { }
1211 1216
1212 void Generate(MacroAssembler* masm); 1217 void Generate(MacroAssembler* masm);
1213 1218
1214 private: 1219 private:
1215 int argc_; 1220 int argc_;
1221 bool call_constructor_;
1216 1222
1217 #ifdef DEBUG 1223 #ifdef DEBUG
1218 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } 1224 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
1219 #endif 1225 #endif
1220 1226
1221 Major MajorKey() { return CallFunction; } 1227 Major MajorKey() { return CallFunction; }
1222 int MinorKey() { return argc_; } 1228 int MinorKey() { return (argc_ << 1) | (call_constructor_ ? 1 : 0); }
1223 }; 1229 };
1224 1230
1225 1231
1226 // Call the function just below TOS on the stack with the given 1232 // Call the function just below TOS on the stack with the given
1227 // arguments. The receiver is the TOS. 1233 // arguments. The receiver is the TOS.
1228 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1234 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1229 int position) { 1235 bool call_constructor,
iposva 2008/10/10 13:56:18 Please change the bool parameter to an enum {FUNCT
1236 int position) {
1230 // Push the arguments ("left-to-right") on the stack. 1237 // Push the arguments ("left-to-right") on the stack.
1231 for (int i = 0; i < args->length(); i++) { 1238 for (int i = 0; i < args->length(); i++) {
1232 Load(args->at(i)); 1239 Load(args->at(i));
1233 } 1240 }
1234 1241
1235 // Record the position for debugging purposes. 1242 // Record the position for debugging purposes.
1236 __ RecordPosition(position); 1243 __ RecordPosition(position);
1237 1244
1238 // Use the shared code stub to call the function. 1245 // Use the shared code stub to call the function.
1239 CallFunctionStub call_function(args->length()); 1246 CallFunctionStub call_function(args->length(), call_constructor);
1240 __ CallStub(&call_function); 1247 RelocInfo::Mode mode = call_constructor
1248 ? RelocInfo::CONSTRUCT_CALL
1249 : RelocInfo::CODE_TARGET;
1250 __ CallStub(&call_function, mode);
1241 1251
1242 // Restore context and pop function from the stack. 1252 // Restore context and pop function from the stack.
1243 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1253 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1244 __ mov(TOS, eax); 1254 __ mov(TOS, eax);
1245 } 1255 }
1246 1256
1247 1257
1248 void CodeGenerator::Branch(bool if_true, Label* L) { 1258 void CodeGenerator::Branch(bool if_true, Label* L) {
1249 ASSERT(has_cc()); 1259 ASSERT(has_cc());
1250 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1260 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after
2590 __ push(Operand(esi)); 2600 __ push(Operand(esi));
2591 __ push(Immediate(var->name())); 2601 __ push(Immediate(var->name()));
2592 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2602 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2593 // eax: slot value; edx: receiver 2603 // eax: slot value; edx: receiver
2594 2604
2595 // Load the receiver. 2605 // Load the receiver.
2596 __ push(eax); 2606 __ push(eax);
2597 __ push(edx); 2607 __ push(edx);
2598 2608
2599 // Call the function. 2609 // Call the function.
2600 CallWithArguments(args, node->position()); 2610 CallWithArguments(args, false, node->position());
2601 2611
2602 } else if (property != NULL) { 2612 } else if (property != NULL) {
2603 // Check if the key is a literal string. 2613 // Check if the key is a literal string.
2604 Literal* literal = property->key()->AsLiteral(); 2614 Literal* literal = property->key()->AsLiteral();
2605 2615
2606 if (literal != NULL && literal->handle()->IsSymbol()) { 2616 if (literal != NULL && literal->handle()->IsSymbol()) {
2607 // ------------------------------------------------------------------ 2617 // ------------------------------------------------------------------
2608 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2618 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2609 // ------------------------------------------------------------------ 2619 // ------------------------------------------------------------------
2610 2620
(...skipping 20 matching lines...) Expand all
2631 2641
2632 // Load the function to call from the property through a reference. 2642 // Load the function to call from the property through a reference.
2633 Reference ref(this, property); 2643 Reference ref(this, property);
2634 ref.GetValue(NOT_INSIDE_TYPEOF); 2644 ref.GetValue(NOT_INSIDE_TYPEOF);
2635 2645
2636 // Pass receiver to called function. 2646 // Pass receiver to called function.
2637 // The reference's size is non-negative. 2647 // The reference's size is non-negative.
2638 __ push(Operand(esp, ref.size() * kPointerSize)); 2648 __ push(Operand(esp, ref.size() * kPointerSize));
2639 2649
2640 // Call the function. 2650 // Call the function.
2641 CallWithArguments(args, node->position()); 2651 CallWithArguments(args, false, node->position());
2642 } 2652 }
2643 2653
2644 } else { 2654 } else {
2645 // ---------------------------------- 2655 // ----------------------------------
2646 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2656 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2647 // ---------------------------------- 2657 // ----------------------------------
2648 2658
2649 // Load the function. 2659 // Load the function.
2650 Load(function); 2660 Load(function);
2651 2661
2652 // Pass the global object as the receiver. 2662 // Pass the global object as the receiver.
2653 LoadGlobal(); 2663 LoadGlobal();
2654 2664
2655 // Call the function. 2665 // Call the function.
2656 CallWithArguments(args, node->position()); 2666 CallWithArguments(args, false, node->position());
2657 } 2667 }
2658 } 2668 }
2659 2669
2660 2670
2661 void CodeGenerator::VisitCallNew(CallNew* node) { 2671 void CodeGenerator::VisitCallNew(CallNew* node) {
2662 Comment cmnt(masm_, "[ CallNew"); 2672 Comment cmnt(masm_, "[ CallNew");
2663 2673
2664 // According to ECMA-262, section 11.2.2, page 44, the function 2674 // According to ECMA-262, section 11.2.2, page 44, the function
2665 // expression in new calls must be evaluated before the 2675 // expression in new calls must be evaluated before the
2666 // arguments. This is different from ordinary calls, where the 2676 // arguments. This is different from ordinary calls, where the
2667 // actual function to call is resolved after the arguments have been 2677 // actual function to call is resolved after the arguments have been
2668 // evaluated. 2678 // evaluated.
2669 2679
2670 // Compute function to call and use the global object as the 2680 // Compute function to call and use the global object as the
2671 // receiver. 2681 // receiver.
2672 Load(node->expression()); 2682 Load(node->expression());
2673 LoadGlobal(); 2683 LoadGlobal();
2674 2684
2675 // Push the arguments ("left-to-right") on the stack. 2685 CallWithArguments(node->arguments(), true, node->position());
iposva 2008/10/10 13:56:18 Nice refactoring!
2676 ZoneList<Expression*>* args = node->arguments();
2677 for (int i = 0; i < args->length(); i++) Load(args->at(i));
2678
2679 // Constructors are called with the number of arguments in register
2680 // eax for now. Another option would be to have separate construct
2681 // call trampolines per different arguments counts encountered.
2682 __ Set(eax, Immediate(args->length()));
2683
2684 // Load the function into temporary function slot as per calling
2685 // convention.
2686 __ mov(edi, Operand(esp, (args->length() + 1) * kPointerSize));
2687
2688 // Call the construct call builtin that handles allocation and
2689 // constructor invocation.
2690 __ RecordPosition(node->position());
2691 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
2692 RelocInfo::CONSTRUCT_CALL);
2693 __ mov(TOS, eax); // discard the function and "push" the newly created object
2694 } 2686 }
2695 2687
2696 2688
2697 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2689 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2698 ASSERT(args->length() == 1); 2690 ASSERT(args->length() == 1);
2699 Load(args->at(0)); 2691 Load(args->at(0));
2700 __ pop(eax); 2692 __ pop(eax);
2701 __ test(eax, Immediate(kSmiTagMask)); 2693 __ test(eax, Immediate(kSmiTagMask));
2702 cc_reg_ = zero; 2694 cc_reg_ = zero;
2703 } 2695 }
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after
4646 // Check that the function really is a JavaScript function. 4638 // Check that the function really is a JavaScript function.
4647 __ test(edi, Immediate(kSmiTagMask)); 4639 __ test(edi, Immediate(kSmiTagMask));
4648 __ j(zero, &slow, not_taken); 4640 __ j(zero, &slow, not_taken);
4649 // Get the map. 4641 // Get the map.
4650 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 4642 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
4651 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 4643 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
4652 __ cmp(ecx, JS_FUNCTION_TYPE); 4644 __ cmp(ecx, JS_FUNCTION_TYPE);
4653 __ j(not_equal, &slow, not_taken); 4645 __ j(not_equal, &slow, not_taken);
4654 4646
4655 // Fast-case: Just invoke the function. 4647 // Fast-case: Just invoke the function.
4656 ParameterCount actual(argc_); 4648 if (call_constructor_) {
4657 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 4649 __ Set(eax, Immediate(argc_));
4650 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
4651 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
4652 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kConstructorOffset));
4653 __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
4654 __ jmp(Operand(edx));
4655 } else {
4656 ParameterCount actual(argc_);
4657 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
4658 }
4658 4659
4659 // Slow-case: Non-function called. 4660 // Slow-case: Non-function called.
4660 __ bind(&slow); 4661 __ bind(&slow);
4661 __ Set(eax, Immediate(argc_)); 4662 if (call_constructor_) {
4662 __ Set(ebx, Immediate(0)); 4663 // Get rid of the arguments and the receiver and call the NewObject
4663 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 4664 // runtime function to generate and throw an exception.
4664 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 4665 __ pop(ecx);
4665 __ jmp(adaptor, RelocInfo::CODE_TARGET); 4666 __ add(Operand(esp), Immediate((argc_ + 1) * kPointerSize));
4667 __ push(ecx);
4668 __ TailCallRuntime(ExternalReference(Runtime::kNewObject), 1);
4669 } else {
4670 __ Set(eax, Immediate(argc_));
4671 __ Set(ebx, Immediate(0));
4672 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
4673 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline) );
4674 __ jmp(adaptor, RelocInfo::CODE_TARGET);
4675 }
4666 } 4676 }
4667 4677
4668 4678
4669 void RevertToNumberStub::Generate(MacroAssembler* masm) { 4679 void RevertToNumberStub::Generate(MacroAssembler* masm) {
4670 // Revert optimistic increment/decrement. 4680 // Revert optimistic increment/decrement.
4671 if (is_increment_) { 4681 if (is_increment_) {
4672 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 4682 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
4673 } else { 4683 } else {
4674 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 4684 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
4675 } 4685 }
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
5046 5056
5047 // Slow-case: Go through the JavaScript implementation. 5057 // Slow-case: Go through the JavaScript implementation.
5048 __ bind(&slow); 5058 __ bind(&slow);
5049 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5059 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5050 } 5060 }
5051 5061
5052 5062
5053 #undef __ 5063 #undef __
5054 5064
5055 } } // namespace v8::internal 5065 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/heap.cc » ('j') | src/objects.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698