| 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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 __ mov(eax, Operand(esp, 0)); | 254 __ mov(eax, Operand(esp, 0)); |
| 255 TestAndBranch(eax, &discard, false_label_); | 255 TestAndBranch(eax, &discard, false_label_); |
| 256 __ bind(&discard); | 256 __ bind(&discard); |
| 257 __ Drop(1); | 257 __ Drop(1); |
| 258 __ jmp(true_label_); | 258 __ jmp(true_label_); |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 | 262 |
| 263 | 263 |
| 264 template <> | 264 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 265 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, | 265 switch (slot->type()) { |
| 266 Register scratch) { | |
| 267 switch (source->type()) { | |
| 268 case Slot::PARAMETER: | 266 case Slot::PARAMETER: |
| 269 case Slot::LOCAL: | 267 case Slot::LOCAL: |
| 270 return Operand(ebp, SlotOffset(source)); | 268 return Operand(ebp, SlotOffset(slot)); |
| 271 case Slot::CONTEXT: { | 269 case Slot::CONTEXT: { |
| 272 int context_chain_length = | 270 int context_chain_length = |
| 273 function_->scope()->ContextChainLength(source->var()->scope()); | 271 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 274 __ LoadContext(scratch, context_chain_length); | 272 __ LoadContext(scratch, context_chain_length); |
| 275 return CodeGenerator::ContextOperand(scratch, source->index()); | 273 return CodeGenerator::ContextOperand(scratch, slot->index()); |
| 276 } | 274 } |
| 277 case Slot::LOOKUP: | 275 case Slot::LOOKUP: |
| 278 UNIMPLEMENTED(); | 276 UNREACHABLE(); |
| 279 } | 277 } |
| 280 UNREACHABLE(); | 278 UNREACHABLE(); |
| 281 return Operand(eax, 0); | 279 return Operand(eax, 0); |
| 282 } | 280 } |
| 283 | 281 |
| 284 | 282 |
| 285 void FastCodeGenerator::Move(Register dst, Slot* source) { | 283 void FastCodeGenerator::Move(Register destination, Slot* source) { |
| 286 Operand location = CreateSlotOperand<Operand>(source, dst); | 284 MemOperand location = EmitSlotSearch(source, destination); |
| 287 __ mov(dst, location); | 285 __ mov(destination, location); |
| 288 } | 286 } |
| 289 | 287 |
| 290 | 288 |
| 291 void FastCodeGenerator::Move(Expression::Context context, | 289 void FastCodeGenerator::Move(Expression::Context context, |
| 292 Slot* source, | 290 Slot* source, |
| 293 Register scratch) { | 291 Register scratch) { |
| 294 switch (context) { | 292 switch (context) { |
| 295 case Expression::kUninitialized: | 293 case Expression::kUninitialized: |
| 296 UNREACHABLE(); | 294 UNREACHABLE(); |
| 297 case Expression::kEffect: | 295 case Expression::kEffect: |
| 298 break; | 296 break; |
| 299 case Expression::kValue: { | 297 case Expression::kValue: { |
| 300 Operand location = CreateSlotOperand<Operand>(source, scratch); | 298 MemOperand location = EmitSlotSearch(source, scratch); |
| 301 __ push(location); | 299 __ push(location); |
| 302 break; | 300 break; |
| 303 } | 301 } |
| 304 case Expression::kTest: | 302 case Expression::kTest: |
| 305 case Expression::kValueTest: | 303 case Expression::kValueTest: |
| 306 case Expression::kTestValue: | 304 case Expression::kTestValue: |
| 307 Move(scratch, source); | 305 Move(scratch, source); |
| 308 Move(context, scratch); | 306 Move(context, scratch); |
| 309 break; | 307 break; |
| 310 } | 308 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 327 Move(context, eax); | 325 Move(context, eax); |
| 328 break; | 326 break; |
| 329 } | 327 } |
| 330 } | 328 } |
| 331 | 329 |
| 332 | 330 |
| 333 void FastCodeGenerator::Move(Slot* dst, | 331 void FastCodeGenerator::Move(Slot* dst, |
| 334 Register src, | 332 Register src, |
| 335 Register scratch1, | 333 Register scratch1, |
| 336 Register scratch2) { | 334 Register scratch2) { |
| 337 switch (dst->type()) { | 335 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 338 case Slot::PARAMETER: | 336 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 339 case Slot::LOCAL: | 337 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 340 __ mov(Operand(ebp, SlotOffset(dst)), src); | 338 __ mov(location, src); |
| 341 break; | 339 // Emit the write barrier code if the location is in the heap. |
| 342 case Slot::CONTEXT: { | 340 if (dst->type() == Slot::CONTEXT) { |
| 343 ASSERT(!src.is(scratch1)); | 341 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 344 ASSERT(!src.is(scratch2)); | 342 __ RecordWrite(scratch1, offset, src, scratch2); |
| 345 ASSERT(!scratch1.is(scratch2)); | |
| 346 int context_chain_length = | |
| 347 function_->scope()->ContextChainLength(dst->var()->scope()); | |
| 348 __ LoadContext(scratch1, context_chain_length); | |
| 349 __ mov(Operand(scratch1, Context::SlotOffset(dst->index())), src); | |
| 350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | |
| 351 __ RecordWrite(scratch1, offset, src, scratch2); | |
| 352 break; | |
| 353 } | |
| 354 case Slot::LOOKUP: | |
| 355 UNIMPLEMENTED(); | |
| 356 } | 343 } |
| 357 } | 344 } |
| 358 | 345 |
| 359 | 346 |
| 360 void FastCodeGenerator::DropAndMove(Expression::Context context, | 347 void FastCodeGenerator::DropAndMove(Expression::Context context, |
| 361 Register source, | 348 Register source, |
| 362 int count) { | 349 int count) { |
| 363 ASSERT(count > 0); | 350 ASSERT(count > 0); |
| 364 switch (context) { | 351 switch (context) { |
| 365 case Expression::kUninitialized: | 352 case Expression::kUninitialized: |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 Variable* var = decl->proxy()->var(); | 428 Variable* var = decl->proxy()->var(); |
| 442 ASSERT(var != NULL); // Must have been resolved. | 429 ASSERT(var != NULL); // Must have been resolved. |
| 443 Slot* slot = var->slot(); | 430 Slot* slot = var->slot(); |
| 444 Property* prop = var->AsProperty(); | 431 Property* prop = var->AsProperty(); |
| 445 | 432 |
| 446 if (slot != NULL) { | 433 if (slot != NULL) { |
| 447 switch (slot->type()) { | 434 switch (slot->type()) { |
| 448 case Slot::PARAMETER: | 435 case Slot::PARAMETER: |
| 449 case Slot::LOCAL: | 436 case Slot::LOCAL: |
| 450 if (decl->mode() == Variable::CONST) { | 437 if (decl->mode() == Variable::CONST) { |
| 451 __ mov(Operand(ebp, SlotOffset(var->slot())), | 438 __ mov(Operand(ebp, SlotOffset(slot)), |
| 452 Immediate(Factory::the_hole_value())); | 439 Immediate(Factory::the_hole_value())); |
| 453 } else if (decl->fun() != NULL) { | 440 } else if (decl->fun() != NULL) { |
| 454 Visit(decl->fun()); | 441 Visit(decl->fun()); |
| 455 __ pop(Operand(ebp, SlotOffset(var->slot()))); | 442 __ pop(Operand(ebp, SlotOffset(slot))); |
| 456 } | 443 } |
| 457 break; | 444 break; |
| 458 | 445 |
| 459 case Slot::CONTEXT: | 446 case Slot::CONTEXT: |
| 447 // We bypass the general EmitSlotSearch because we know more about |
| 448 // this specific context. |
| 449 |
| 460 // The variable in the decl always resides in the current context. | 450 // The variable in the decl always resides in the current context. |
| 461 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); | 451 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); |
| 462 if (FLAG_debug_code) { | 452 if (FLAG_debug_code) { |
| 463 // Check if we have the correct context pointer. | 453 // Check if we have the correct context pointer. |
| 464 __ mov(ebx, | 454 __ mov(ebx, |
| 465 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); | 455 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); |
| 466 __ cmp(ebx, Operand(esi)); | 456 __ cmp(ebx, Operand(esi)); |
| 467 __ Check(equal, "Unexpected declaration in current context."); | 457 __ Check(equal, "Unexpected declaration in current context."); |
| 468 } | 458 } |
| 469 if (decl->mode() == Variable::CONST) { | 459 if (decl->mode() == Variable::CONST) { |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 887 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 898 __ call(ic, RelocInfo::CODE_TARGET); | 888 __ call(ic, RelocInfo::CODE_TARGET); |
| 899 // Overwrite the receiver on the stack with the result if needed. | 889 // Overwrite the receiver on the stack with the result if needed. |
| 900 DropAndMove(context, eax); | 890 DropAndMove(context, eax); |
| 901 | 891 |
| 902 } else if (var->slot() != NULL) { | 892 } else if (var->slot() != NULL) { |
| 903 Slot* slot = var->slot(); | 893 Slot* slot = var->slot(); |
| 904 switch (slot->type()) { | 894 switch (slot->type()) { |
| 905 case Slot::LOCAL: | 895 case Slot::LOCAL: |
| 906 case Slot::PARAMETER: { | 896 case Slot::PARAMETER: { |
| 907 Operand target = Operand(ebp, SlotOffset(var->slot())); | 897 Operand target = Operand(ebp, SlotOffset(slot)); |
| 908 switch (context) { | 898 switch (context) { |
| 909 case Expression::kUninitialized: | 899 case Expression::kUninitialized: |
| 910 UNREACHABLE(); | 900 UNREACHABLE(); |
| 911 case Expression::kEffect: | 901 case Expression::kEffect: |
| 912 // Perform assignment and discard value. | 902 // Perform assignment and discard value. |
| 913 __ pop(target); | 903 __ pop(target); |
| 914 break; | 904 break; |
| 915 case Expression::kValue: | 905 case Expression::kValue: |
| 916 // Perform assignment and preserve value. | 906 // Perform assignment and preserve value. |
| 917 __ mov(eax, Operand(esp, 0)); | 907 __ mov(eax, Operand(esp, 0)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 941 __ bind(&discard); | 931 __ bind(&discard); |
| 942 __ add(Operand(esp), Immediate(kPointerSize)); | 932 __ add(Operand(esp), Immediate(kPointerSize)); |
| 943 __ jmp(true_label_); | 933 __ jmp(true_label_); |
| 944 break; | 934 break; |
| 945 } | 935 } |
| 946 } | 936 } |
| 947 break; | 937 break; |
| 948 } | 938 } |
| 949 | 939 |
| 950 case Slot::CONTEXT: { | 940 case Slot::CONTEXT: { |
| 951 int chain_length = | 941 MemOperand target = EmitSlotSearch(slot, ecx); |
| 952 function_->scope()->ContextChainLength(slot->var()->scope()); | 942 __ pop(eax); |
| 953 if (chain_length > 0) { | 943 __ mov(target, eax); |
| 954 // Move up the context chain to the context containing the slot. | |
| 955 __ mov(eax, | |
| 956 Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
| 957 // Load the function context (which is the incoming, outer context). | |
| 958 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); | |
| 959 for (int i = 1; i < chain_length; i++) { | |
| 960 __ mov(eax, | |
| 961 Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
| 962 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); | |
| 963 } | |
| 964 } else { // Slot is in the current context. Generate optimized code. | |
| 965 __ mov(eax, esi); // RecordWrite destroys the object register. | |
| 966 } | |
| 967 if (FLAG_debug_code) { | |
| 968 __ cmp(eax, | |
| 969 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); | |
| 970 __ Check(equal, "Context Slot chain length wrong."); | |
| 971 } | |
| 972 __ pop(ecx); | |
| 973 __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx); | |
| 974 | 944 |
| 975 // RecordWrite may destroy all its register arguments. | 945 // RecordWrite may destroy all its register arguments. |
| 976 if (context == Expression::kValue) { | 946 if (context == Expression::kValue) { |
| 977 __ push(ecx); | 947 __ push(eax); |
| 978 } else if (context != Expression::kEffect) { | 948 } else if (context != Expression::kEffect) { |
| 979 __ mov(edx, ecx); | 949 __ mov(edx, eax); |
| 980 } | 950 } |
| 981 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 982 __ RecordWrite(eax, offset, ecx, ebx); | 952 __ RecordWrite(ecx, offset, eax, ebx); |
| 983 if (context != Expression::kEffect && | 953 if (context != Expression::kEffect && |
| 984 context != Expression::kValue) { | 954 context != Expression::kValue) { |
| 985 Move(context, edx); | 955 Move(context, edx); |
| 986 } | 956 } |
| 987 break; | 957 break; |
| 988 } | 958 } |
| 989 | 959 |
| 990 case Slot::LOOKUP: | 960 case Slot::LOOKUP: |
| 991 UNREACHABLE(); | 961 UNREACHABLE(); |
| 992 break; | 962 break; |
| 993 } | 963 } |
| 964 } else { |
| 965 // Variables rewritten as properties are not treated as variables in |
| 966 // assignments. |
| 967 UNREACHABLE(); |
| 994 } | 968 } |
| 995 } | 969 } |
| 996 | 970 |
| 997 | 971 |
| 998 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 972 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 999 // Assignment to a property, using a named store IC. | 973 // Assignment to a property, using a named store IC. |
| 1000 Property* prop = expr->target()->AsProperty(); | 974 Property* prop = expr->target()->AsProperty(); |
| 1001 ASSERT(prop != NULL); | 975 ASSERT(prop != NULL); |
| 1002 ASSERT(prop->key()->AsLiteral() != NULL); | 976 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1003 | 977 |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1793 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1767 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
| 1794 __ mov(Operand(esp, 0), edx); | 1768 __ mov(Operand(esp, 0), edx); |
| 1795 // And return. | 1769 // And return. |
| 1796 __ ret(0); | 1770 __ ret(0); |
| 1797 } | 1771 } |
| 1798 | 1772 |
| 1799 | 1773 |
| 1800 #undef __ | 1774 #undef __ |
| 1801 | 1775 |
| 1802 } } // namespace v8::internal | 1776 } } // namespace v8::internal |
| OLD | NEW |