| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 __ movq(rax, Operand(rsp, 0)); | 263 __ movq(rax, Operand(rsp, 0)); |
| 264 TestAndBranch(rax, &discard, false_label_); | 264 TestAndBranch(rax, &discard, false_label_); |
| 265 __ bind(&discard); | 265 __ bind(&discard); |
| 266 __ Drop(1); | 266 __ Drop(1); |
| 267 __ jmp(true_label_); | 267 __ jmp(true_label_); |
| 268 } | 268 } |
| 269 } | 269 } |
| 270 } | 270 } |
| 271 | 271 |
| 272 | 272 |
| 273 template <> | 273 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 274 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, | 274 switch (slot->type()) { |
| 275 Register scratch) { | |
| 276 switch (source->type()) { | |
| 277 case Slot::PARAMETER: | 275 case Slot::PARAMETER: |
| 278 case Slot::LOCAL: | 276 case Slot::LOCAL: |
| 279 return Operand(rbp, SlotOffset(source)); | 277 return Operand(rbp, SlotOffset(slot)); |
| 280 case Slot::CONTEXT: { | 278 case Slot::CONTEXT: { |
| 281 int context_chain_length = | 279 int context_chain_length = |
| 282 function_->scope()->ContextChainLength(source->var()->scope()); | 280 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 283 __ LoadContext(scratch, context_chain_length); | 281 __ LoadContext(scratch, context_chain_length); |
| 284 return CodeGenerator::ContextOperand(scratch, source->index()); | 282 return CodeGenerator::ContextOperand(scratch, slot->index()); |
| 285 } | 283 } |
| 286 case Slot::LOOKUP: | 284 case Slot::LOOKUP: |
| 287 UNIMPLEMENTED(); | 285 UNREACHABLE(); |
| 288 } | 286 } |
| 289 UNREACHABLE(); | 287 UNREACHABLE(); |
| 290 return Operand(rax, 0); | 288 return Operand(rax, 0); |
| 291 } | 289 } |
| 292 | 290 |
| 293 | 291 |
| 294 void FastCodeGenerator::Move(Register dst, Slot* source) { | 292 void FastCodeGenerator::Move(Register destination, Slot* source) { |
| 295 Operand location = CreateSlotOperand<Operand>(source, dst); | 293 MemOperand location = EmitSlotSearch(source, destination); |
| 296 __ movq(dst, location); | 294 __ movq(destination, location); |
| 297 } | 295 } |
| 298 | 296 |
| 299 | 297 |
| 300 void FastCodeGenerator::Move(Expression::Context context, | 298 void FastCodeGenerator::Move(Expression::Context context, |
| 301 Slot* source, | 299 Slot* source, |
| 302 Register scratch) { | 300 Register scratch) { |
| 303 switch (context) { | 301 switch (context) { |
| 304 case Expression::kUninitialized: | 302 case Expression::kUninitialized: |
| 305 UNREACHABLE(); | 303 UNREACHABLE(); |
| 306 case Expression::kEffect: | 304 case Expression::kEffect: |
| 307 break; | 305 break; |
| 308 case Expression::kValue: { | 306 case Expression::kValue: { |
| 309 Operand location = CreateSlotOperand<Operand>(source, scratch); | 307 MemOperand location = EmitSlotSearch(source, scratch); |
| 310 __ push(location); | 308 __ push(location); |
| 311 break; | 309 break; |
| 312 } | 310 } |
| 313 case Expression::kTest: | 311 case Expression::kTest: |
| 314 case Expression::kValueTest: | 312 case Expression::kValueTest: |
| 315 case Expression::kTestValue: | 313 case Expression::kTestValue: |
| 316 Move(scratch, source); | 314 Move(scratch, source); |
| 317 Move(context, scratch); | 315 Move(context, scratch); |
| 318 break; | 316 break; |
| 319 } | 317 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 336 Move(context, rax); | 334 Move(context, rax); |
| 337 break; | 335 break; |
| 338 } | 336 } |
| 339 } | 337 } |
| 340 | 338 |
| 341 | 339 |
| 342 void FastCodeGenerator::Move(Slot* dst, | 340 void FastCodeGenerator::Move(Slot* dst, |
| 343 Register src, | 341 Register src, |
| 344 Register scratch1, | 342 Register scratch1, |
| 345 Register scratch2) { | 343 Register scratch2) { |
| 346 switch (dst->type()) { | 344 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 347 case Slot::PARAMETER: | 345 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 348 case Slot::LOCAL: | 346 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 349 __ movq(Operand(rbp, SlotOffset(dst)), src); | 347 __ movq(location, src); |
| 350 break; | 348 // Emit the write barrier code if the location is in the heap. |
| 351 case Slot::CONTEXT: { | 349 if (dst->type() == Slot::CONTEXT) { |
| 352 ASSERT(!src.is(scratch1)); | 350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 353 ASSERT(!src.is(scratch2)); | 351 __ RecordWrite(scratch1, offset, src, scratch2); |
| 354 ASSERT(!scratch1.is(scratch2)); | |
| 355 int context_chain_length = | |
| 356 function_->scope()->ContextChainLength(dst->var()->scope()); | |
| 357 __ LoadContext(scratch1, context_chain_length); | |
| 358 __ movq(Operand(scratch1, Context::SlotOffset(dst->index())), src); | |
| 359 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | |
| 360 __ RecordWrite(scratch1, offset, src, scratch2); | |
| 361 break; | |
| 362 } | |
| 363 case Slot::LOOKUP: | |
| 364 UNIMPLEMENTED(); | |
| 365 } | 352 } |
| 366 } | 353 } |
| 367 | 354 |
| 368 | 355 |
| 369 void FastCodeGenerator::DropAndMove(Expression::Context context, | 356 void FastCodeGenerator::DropAndMove(Expression::Context context, |
| 370 Register source, | 357 Register source, |
| 371 int drop_count) { | 358 int drop_count) { |
| 372 ASSERT(drop_count > 0); | 359 ASSERT(drop_count > 0); |
| 373 switch (context) { | 360 switch (context) { |
| 374 case Expression::kUninitialized: | 361 case Expression::kUninitialized: |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 ASSERT(var != NULL); // Must have been resolved. | 437 ASSERT(var != NULL); // Must have been resolved. |
| 451 Slot* slot = var->slot(); | 438 Slot* slot = var->slot(); |
| 452 Property* prop = var->AsProperty(); | 439 Property* prop = var->AsProperty(); |
| 453 | 440 |
| 454 if (slot != NULL) { | 441 if (slot != NULL) { |
| 455 switch (slot->type()) { | 442 switch (slot->type()) { |
| 456 case Slot::PARAMETER: | 443 case Slot::PARAMETER: |
| 457 case Slot::LOCAL: | 444 case Slot::LOCAL: |
| 458 if (decl->mode() == Variable::CONST) { | 445 if (decl->mode() == Variable::CONST) { |
| 459 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 446 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
| 460 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 447 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); |
| 461 } else if (decl->fun() != NULL) { | 448 } else if (decl->fun() != NULL) { |
| 462 Visit(decl->fun()); | 449 Visit(decl->fun()); |
| 463 __ pop(Operand(rbp, SlotOffset(var->slot()))); | 450 __ pop(Operand(rbp, SlotOffset(slot))); |
| 464 } | 451 } |
| 465 break; | 452 break; |
| 466 | 453 |
| 467 case Slot::CONTEXT: | 454 case Slot::CONTEXT: |
| 455 // We bypass the general EmitSlotSearch because we know more about |
| 456 // this specific context. |
| 457 |
| 468 // The variable in the decl always resides in the current context. | 458 // The variable in the decl always resides in the current context. |
| 469 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); | 459 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); |
| 470 if (FLAG_debug_code) { | 460 if (FLAG_debug_code) { |
| 471 // Check if we have the correct context pointer. | 461 // Check if we have the correct context pointer. |
| 472 __ movq(rbx, | 462 __ movq(rbx, |
| 473 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); | 463 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); |
| 474 __ cmpq(rbx, rsi); | 464 __ cmpq(rbx, rsi); |
| 475 __ Check(equal, "Unexpected declaration in current context."); | 465 __ Check(equal, "Unexpected declaration in current context."); |
| 476 } | 466 } |
| 477 if (decl->mode() == Variable::CONST) { | 467 if (decl->mode() == Variable::CONST) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 // assignment. Right-hand-side value is passed in rax, variable name in | 891 // assignment. Right-hand-side value is passed in rax, variable name in |
| 902 // rcx, and the global object on the stack. | 892 // rcx, and the global object on the stack. |
| 903 __ pop(rax); | 893 __ pop(rax); |
| 904 __ Move(rcx, var->name()); | 894 __ Move(rcx, var->name()); |
| 905 __ push(CodeGenerator::GlobalObject()); | 895 __ push(CodeGenerator::GlobalObject()); |
| 906 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 896 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 907 __ Call(ic, RelocInfo::CODE_TARGET); | 897 __ Call(ic, RelocInfo::CODE_TARGET); |
| 908 // Overwrite the global object on the stack with the result if needed. | 898 // Overwrite the global object on the stack with the result if needed. |
| 909 DropAndMove(context, rax); | 899 DropAndMove(context, rax); |
| 910 | 900 |
| 911 } else if (var->slot()) { | 901 } else if (var->slot() != NULL) { |
| 912 Slot* slot = var->slot(); | 902 Slot* slot = var->slot(); |
| 913 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. | |
| 914 switch (slot->type()) { | 903 switch (slot->type()) { |
| 915 case Slot::LOCAL: | 904 case Slot::LOCAL: |
| 916 case Slot::PARAMETER: { | 905 case Slot::PARAMETER: { |
| 906 Operand target = Operand(rbp, SlotOffset(slot)); |
| 917 switch (context) { | 907 switch (context) { |
| 918 case Expression::kUninitialized: | 908 case Expression::kUninitialized: |
| 919 UNREACHABLE(); | 909 UNREACHABLE(); |
| 920 case Expression::kEffect: | 910 case Expression::kEffect: |
| 921 // Perform assignment and discard value. | 911 // Perform assignment and discard value. |
| 922 __ pop(Operand(rbp, SlotOffset(var->slot()))); | 912 __ pop(target); |
| 923 break; | 913 break; |
| 924 case Expression::kValue: | 914 case Expression::kValue: |
| 925 // Perform assignment and preserve value. | 915 // Perform assignment and preserve value. |
| 926 __ movq(rax, Operand(rsp, 0)); | 916 __ movq(rax, Operand(rsp, 0)); |
| 927 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 917 __ movq(target, rax); |
| 928 break; | 918 break; |
| 929 case Expression::kTest: | 919 case Expression::kTest: |
| 930 // Perform assignment and test (and discard) value. | 920 // Perform assignment and test (and discard) value. |
| 931 __ pop(rax); | 921 __ pop(rax); |
| 932 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 922 __ movq(target, rax); |
| 933 TestAndBranch(rax, true_label_, false_label_); | 923 TestAndBranch(rax, true_label_, false_label_); |
| 934 break; | 924 break; |
| 935 case Expression::kValueTest: { | 925 case Expression::kValueTest: { |
| 936 Label discard; | 926 Label discard; |
| 937 __ movq(rax, Operand(rsp, 0)); | 927 __ movq(rax, Operand(rsp, 0)); |
| 938 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 928 __ movq(target, rax); |
| 939 TestAndBranch(rax, true_label_, &discard); | 929 TestAndBranch(rax, true_label_, &discard); |
| 940 __ bind(&discard); | 930 __ bind(&discard); |
| 941 __ addq(rsp, Immediate(kPointerSize)); | 931 __ addq(rsp, Immediate(kPointerSize)); |
| 942 __ jmp(false_label_); | 932 __ jmp(false_label_); |
| 943 break; | 933 break; |
| 944 } | 934 } |
| 945 case Expression::kTestValue: { | 935 case Expression::kTestValue: { |
| 946 Label discard; | 936 Label discard; |
| 947 __ movq(rax, Operand(rsp, 0)); | 937 __ movq(rax, Operand(rsp, 0)); |
| 948 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 938 __ movq(target, rax); |
| 949 TestAndBranch(rax, &discard, false_label_); | 939 TestAndBranch(rax, &discard, false_label_); |
| 950 __ bind(&discard); | 940 __ bind(&discard); |
| 951 __ addq(rsp, Immediate(kPointerSize)); | 941 __ addq(rsp, Immediate(kPointerSize)); |
| 952 __ jmp(true_label_); | 942 __ jmp(true_label_); |
| 953 break; | 943 break; |
| 954 } | 944 } |
| 955 } | 945 } |
| 956 break; | 946 break; |
| 957 } | 947 } |
| 958 | 948 |
| 959 case Slot::CONTEXT: { | 949 case Slot::CONTEXT: { |
| 960 int chain_length = | 950 MemOperand target = EmitSlotSearch(slot, rcx); |
| 961 function_->scope()->ContextChainLength(slot->var()->scope()); | 951 __ pop(rax); |
| 962 if (chain_length > 0) { | 952 __ movq(target, rax); |
| 963 // Move up the context chain to the context containing the slot. | |
| 964 __ movq(rax, | |
| 965 Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
| 966 // Load the function context (which is the incoming, outer context). | |
| 967 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset)); | |
| 968 for (int i = 1; i < chain_length; i++) { | |
| 969 __ movq(rax, | |
| 970 Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
| 971 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset)); | |
| 972 } | |
| 973 } else { // Slot is in the current context. Generate optimized code. | |
| 974 __ movq(rax, rsi); // RecordWrite destroys the object register. | |
| 975 } | |
| 976 if (FLAG_debug_code) { | |
| 977 __ cmpq(rax, | |
| 978 Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX))); | |
| 979 __ Check(equal, "Context Slot chain length wrong."); | |
| 980 } | |
| 981 __ pop(rcx); | |
| 982 __ movq(Operand(rax, Context::SlotOffset(slot->index())), rcx); | |
| 983 | 953 |
| 984 // RecordWrite may destroy all its register arguments. | 954 // RecordWrite may destroy all its register arguments. |
| 985 if (context == Expression::kValue) { | 955 if (context == Expression::kValue) { |
| 986 __ push(rcx); | 956 __ push(rax); |
| 987 } else if (context != Expression::kEffect) { | 957 } else if (context != Expression::kEffect) { |
| 988 __ movq(rdx, rcx); | 958 __ movq(rdx, rax); |
| 989 } | 959 } |
| 990 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 960 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 991 __ RecordWrite(rax, offset, rcx, rbx); | 961 __ RecordWrite(rcx, offset, rax, rbx); |
| 992 if (context != Expression::kEffect && | 962 if (context != Expression::kEffect && |
| 993 context != Expression::kValue) { | 963 context != Expression::kValue) { |
| 994 Move(context, rdx); | 964 Move(context, rdx); |
| 995 } | 965 } |
| 996 break; | 966 break; |
| 997 } | 967 } |
| 998 | 968 |
| 999 case Slot::LOOKUP: | 969 case Slot::LOOKUP: |
| 1000 UNREACHABLE(); | 970 UNREACHABLE(); |
| 1001 break; | 971 break; |
| 1002 } | 972 } |
| 973 } else { |
| 974 // Variables rewritten as properties are not treated as variables in |
| 975 // assignments. |
| 976 UNREACHABLE(); |
| 1003 } | 977 } |
| 1004 } | 978 } |
| 1005 | 979 |
| 1006 | 980 |
| 1007 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 981 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1008 // Assignment to a property, using a named store IC. | 982 // Assignment to a property, using a named store IC. |
| 1009 Property* prop = expr->target()->AsProperty(); | 983 Property* prop = expr->target()->AsProperty(); |
| 1010 ASSERT(prop != NULL); | 984 ASSERT(prop != NULL); |
| 1011 ASSERT(prop->key()->AsLiteral() != NULL); | 985 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1012 | 986 |
| (...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1810 __ movq(Operand(rsp, 0), rdx); | 1784 __ movq(Operand(rsp, 0), rdx); |
| 1811 // And return. | 1785 // And return. |
| 1812 __ ret(0); | 1786 __ ret(0); |
| 1813 } | 1787 } |
| 1814 | 1788 |
| 1815 | 1789 |
| 1816 #undef __ | 1790 #undef __ |
| 1817 | 1791 |
| 1818 | 1792 |
| 1819 } } // namespace v8::internal | 1793 } } // namespace v8::internal |
| OLD | NEW |