Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 3219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3230 int arg_count = args->length(); | 3230 int arg_count = args->length(); |
| 3231 for (int i = 0; i < arg_count; i++) { | 3231 for (int i = 0; i < arg_count; i++) { |
| 3232 Load(args->at(i)); | 3232 Load(args->at(i)); |
| 3233 } | 3233 } |
| 3234 | 3234 |
| 3235 // Setup the receiver register and call the IC initialization code. | 3235 // Setup the receiver register and call the IC initialization code. |
| 3236 Handle<Code> stub = (loop_nesting() > 0) | 3236 Handle<Code> stub = (loop_nesting() > 0) |
| 3237 ? ComputeCallInitializeInLoop(arg_count) | 3237 ? ComputeCallInitializeInLoop(arg_count) |
| 3238 : ComputeCallInitialize(arg_count); | 3238 : ComputeCallInitialize(arg_count); |
| 3239 CodeForSourcePosition(node->position()); | 3239 CodeForSourcePosition(node->position()); |
| 3240 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 3240 Result result = frame_->CallCodeObject(stub, |
| 3241 arg_count + 1); | 3241 RelocInfo::CODE_TARGET_CONTEXT, |
| 3242 Result result = allocator_->Allocate(eax); | 3242 arg_count + 1); |
| 3243 frame_->RestoreContextRegister(); | 3243 frame_->RestoreContextRegister(); |
| 3244 | 3244 |
| 3245 // Replace the function on the stack with the result. | 3245 // Replace the function on the stack with the result. |
| 3246 frame_->SetElementAt(0, &result); | 3246 frame_->SetElementAt(0, &result); |
| 3247 | 3247 |
| 3248 } else if (var != NULL && var->slot() != NULL && | 3248 } else if (var != NULL && var->slot() != NULL && |
| 3249 var->slot()->type() == Slot::LOOKUP) { | 3249 var->slot()->type() == Slot::LOOKUP) { |
| 3250 // ---------------------------------- | 3250 // ---------------------------------- |
| 3251 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 3251 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
| 3252 // ---------------------------------- | 3252 // ---------------------------------- |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 3281 int arg_count = args->length(); | 3281 int arg_count = args->length(); |
| 3282 for (int i = 0; i < arg_count; i++) { | 3282 for (int i = 0; i < arg_count; i++) { |
| 3283 Load(args->at(i)); | 3283 Load(args->at(i)); |
| 3284 } | 3284 } |
| 3285 | 3285 |
| 3286 // Call the IC initialization code. | 3286 // Call the IC initialization code. |
| 3287 Handle<Code> stub = (loop_nesting() > 0) | 3287 Handle<Code> stub = (loop_nesting() > 0) |
| 3288 ? ComputeCallInitializeInLoop(arg_count) | 3288 ? ComputeCallInitializeInLoop(arg_count) |
| 3289 : ComputeCallInitialize(arg_count); | 3289 : ComputeCallInitialize(arg_count); |
| 3290 CodeForSourcePosition(node->position()); | 3290 CodeForSourcePosition(node->position()); |
| 3291 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3291 Result result = frame_->CallCodeObject(stub, |
| 3292 Result result = allocator_->Allocate(eax); | 3292 RelocInfo::CODE_TARGET, |
| 3293 arg_count + 1); | |
| 3293 frame_->RestoreContextRegister(); | 3294 frame_->RestoreContextRegister(); |
| 3294 | 3295 |
| 3295 // Replace the function on the stack with the result. | 3296 // Replace the function on the stack with the result. |
| 3296 frame_->SetElementAt(0, &result); | 3297 frame_->SetElementAt(0, &result); |
| 3297 | 3298 |
| 3298 } else { | 3299 } else { |
| 3299 // ------------------------------------------- | 3300 // ------------------------------------------- |
| 3300 // JavaScript example: 'array[index](1, 2, 3)' | 3301 // JavaScript example: 'array[index](1, 2, 3)' |
| 3301 // ------------------------------------------- | 3302 // ------------------------------------------- |
| 3302 | 3303 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3363 __ Set(eax, Immediate(arg_count)); | 3364 __ Set(eax, Immediate(arg_count)); |
| 3364 | 3365 |
| 3365 // Load the function into temporary function slot as per calling | 3366 // Load the function into temporary function slot as per calling |
| 3366 // convention. | 3367 // convention. |
| 3367 __ mov(edi, frame_->ElementAt(arg_count + 1)); | 3368 __ mov(edi, frame_->ElementAt(arg_count + 1)); |
| 3368 | 3369 |
| 3369 // Call the construct call builtin that handles allocation and | 3370 // Call the construct call builtin that handles allocation and |
| 3370 // constructor invocation. | 3371 // constructor invocation. |
| 3371 CodeForSourcePosition(node->position()); | 3372 CodeForSourcePosition(node->position()); |
| 3372 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3373 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
| 3373 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); | 3374 Result result = frame_->CallCodeObject(ic, |
| 3374 Result result = allocator_->Allocate(eax); | 3375 RelocInfo::CONSTRUCT_CALL, |
| 3376 args->length() + 1); | |
| 3375 | 3377 |
| 3376 // Replace the function on the stack with the result. | 3378 // Replace the function on the stack with the result. |
| 3377 frame_->SetElementAt(0, &result); | 3379 frame_->SetElementAt(0, &result); |
| 3378 } | 3380 } |
| 3379 | 3381 |
| 3380 | 3382 |
| 3381 void CodeGenerator::VisitCallEval(CallEval* node) { | 3383 void CodeGenerator::VisitCallEval(CallEval* node) { |
| 3382 VirtualFrame::SpilledScope spilled_scope(this); | 3384 VirtualFrame::SpilledScope spilled_scope(this); |
| 3383 Comment cmnt(masm_, "[ CallEval"); | 3385 Comment cmnt(masm_, "[ CallEval"); |
| 3384 | 3386 |
| (...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4404 | 4406 |
| 4405 | 4407 |
| 4406 class DeferredReferenceGetKeyedValue: public DeferredCode { | 4408 class DeferredReferenceGetKeyedValue: public DeferredCode { |
| 4407 public: | 4409 public: |
| 4408 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) | 4410 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) |
| 4409 : DeferredCode(generator), is_global_(is_global) { | 4411 : DeferredCode(generator), is_global_(is_global) { |
| 4410 set_comment("[ DeferredReferenceGetKeyedValue"); | 4412 set_comment("[ DeferredReferenceGetKeyedValue"); |
| 4411 } | 4413 } |
| 4412 | 4414 |
| 4413 virtual void Generate() { | 4415 virtual void Generate() { |
| 4414 // The argument are actually passed in edx and on top of the frame. | 4416 CodeGenerator* cgen = generator(); |
| 4415 enter()->Bind(); | |
| 4416 VirtualFrame::SpilledScope spilled_scope(generator()); | |
| 4417 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 4417 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 4418 Result receiver(cgen); | |
| 4419 Result key(cgen); | |
| 4420 enter()->Bind(&receiver, &key); | |
| 4421 VirtualFrame* frame = generator()->frame(); | |
| 4422 frame->Push(&receiver); // First IC argument. | |
| 4423 frame->Push(&key); // Second IC argument. | |
| 4424 | |
| 4418 // Calculate the delta from the IC call instruction to the map | 4425 // Calculate the delta from the IC call instruction to the map |
| 4419 // check cmp instruction in the inlined version. This delta is | 4426 // check cmp instruction in the inlined version. This delta is |
| 4420 // stored in a test(eax, delta) instruction after the call so that | 4427 // stored in a test(eax, delta) instruction after the call so that |
| 4421 // we can find it in the IC initialization code and patch the cmp | 4428 // we can find it in the IC initialization code and patch the cmp |
| 4422 // instruction. This means that we cannot allow test instructions | 4429 // instruction. This means that we cannot allow test instructions |
| 4423 // after calls to KeyedLoadIC stubs in other places. | 4430 // after calls to KeyedLoadIC stubs in other places. |
| 4431 // | |
| 4432 // The virtual frame should be spilled fully before the call so | |
| 4433 // that the call itself does not generate extra code to spill | |
| 4434 // values. | |
| 4435 frame->SpillAll(); | |
| 4424 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); | 4436 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); |
| 4425 VirtualFrame* frame = generator()->frame(); | 4437 Result value(cgen); |
| 4426 if (is_global_) { | 4438 if (is_global_) { |
| 4427 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | 4439 value = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); |
| 4428 } else { | 4440 } else { |
| 4429 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4441 value = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 4430 } | 4442 } |
| 4431 __ test(eax, Immediate(-delta_to_patch_site)); | 4443 // The result needs to be specifically the eax register because |
| 4444 // the offset to the patch site will be expected in a test eax | |
| 4445 // instruction. | |
| 4446 ASSERT(value.is_register() && value.reg().is(eax)); | |
| 4447 __ test(value.reg(), Immediate(-delta_to_patch_site)); | |
| 4432 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 4448 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
| 4433 // The result is result is actually returned in eax. | 4449 exit()->Jump(&value); |
| 4434 exit()->Jump(); | |
| 4435 } | 4450 } |
| 4436 | 4451 |
| 4437 Label* patch_site() { return &patch_site_; } | 4452 Label* patch_site() { return &patch_site_; } |
| 4438 | 4453 |
| 4439 private: | 4454 private: |
| 4440 Label patch_site_; | 4455 Label patch_site_; |
| 4441 bool is_global_; | 4456 bool is_global_; |
| 4442 }; | 4457 }; |
| 4443 | 4458 |
| 4444 | 4459 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 4460 return Handle<String>(String::cast(*raw_name->handle())); | 4475 return Handle<String>(String::cast(*raw_name->handle())); |
| 4461 } | 4476 } |
| 4462 } | 4477 } |
| 4463 | 4478 |
| 4464 | 4479 |
| 4465 void Reference::GetValue(TypeofState typeof_state) { | 4480 void Reference::GetValue(TypeofState typeof_state) { |
| 4466 ASSERT(!cgen_->in_spilled_code()); | 4481 ASSERT(!cgen_->in_spilled_code()); |
| 4467 ASSERT(!is_illegal()); | 4482 ASSERT(!is_illegal()); |
| 4468 ASSERT(!cgen_->has_cc()); | 4483 ASSERT(!cgen_->has_cc()); |
| 4469 MacroAssembler* masm = cgen_->masm(); | 4484 MacroAssembler* masm = cgen_->masm(); |
| 4470 VirtualFrame* frame = cgen_->frame(); | |
| 4471 switch (type_) { | 4485 switch (type_) { |
| 4472 case SLOT: { | 4486 case SLOT: { |
| 4473 Comment cmnt(masm, "[ Load from Slot"); | 4487 Comment cmnt(masm, "[ Load from Slot"); |
| 4474 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 4488 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4475 ASSERT(slot != NULL); | 4489 ASSERT(slot != NULL); |
| 4476 cgen_->LoadFromSlot(slot, typeof_state); | 4490 cgen_->LoadFromSlot(slot, typeof_state); |
| 4477 break; | 4491 break; |
| 4478 } | 4492 } |
| 4479 | 4493 |
| 4480 case NAMED: { | 4494 case NAMED: { |
| 4481 // TODO(1241834): Make sure that it is safe to ignore the | 4495 // TODO(1241834): Make sure that it is safe to ignore the |
| 4482 // distinction between expressions in a typeof and not in a | 4496 // distinction between expressions in a typeof and not in a |
| 4483 // typeof. If there is a chance that reference errors can be | 4497 // typeof. If there is a chance that reference errors can be |
| 4484 // thrown below, we must distinguish between the two kinds of | 4498 // thrown below, we must distinguish between the two kinds of |
| 4485 // loads (typeof expression loads must not throw a reference | 4499 // loads (typeof expression loads must not throw a reference |
| 4486 // error). | 4500 // error). |
| 4487 VirtualFrame::SpilledScope spilled_scope(cgen_); | 4501 VirtualFrame::SpilledScope spilled_scope(cgen_); |
| 4502 VirtualFrame* frame = cgen_->frame(); | |
| 4488 Comment cmnt(masm, "[ Load from named Property"); | 4503 Comment cmnt(masm, "[ Load from named Property"); |
| 4489 Handle<String> name(GetName()); | 4504 Handle<String> name(GetName()); |
| 4490 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4505 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 4491 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 4506 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 4492 // Setup the name register. | 4507 // Setup the name register. |
| 4493 __ mov(ecx, name); | 4508 __ mov(ecx, name); |
| 4494 if (var != NULL) { | 4509 if (var != NULL) { |
| 4495 ASSERT(var->is_global()); | 4510 ASSERT(var->is_global()); |
| 4496 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | 4511 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); |
| 4497 } else { | 4512 } else { |
| 4498 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4513 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 4499 } | 4514 } |
| 4500 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4515 frame->EmitPush(eax); // IC call leaves result in eax, push it out |
| 4501 break; | 4516 break; |
| 4502 } | 4517 } |
| 4503 | 4518 |
| 4504 case KEYED: { | 4519 case KEYED: { |
| 4505 // TODO(1241834): Make sure that this it is safe to ignore the | 4520 // TODO(1241834): Make sure that this it is safe to ignore the |
| 4506 // distinction between expressions in a typeof and not in a typeof. | 4521 // distinction between expressions in a typeof and not in a typeof. |
| 4507 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4508 Comment cmnt(masm, "[ Load from keyed Property"); | 4522 Comment cmnt(masm, "[ Load from keyed Property"); |
| 4509 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
| 4510 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4523 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 4511 bool is_global = var != NULL; | 4524 bool is_global = var != NULL; |
| 4512 ASSERT(!is_global || var->is_global()); | 4525 ASSERT(!is_global || var->is_global()); |
| 4513 // Inline array load code if inside of a loop. We do not know | 4526 // Inline array load code if inside of a loop. We do not know |
| 4514 // the receiver map yet, so we initially generate the code with | 4527 // the receiver map yet, so we initially generate the code with |
| 4515 // a check against an invalid map. In the inline cache code, we | 4528 // a check against an invalid map. In the inline cache code, we |
| 4516 // patch the map check if appropriate. | 4529 // patch the map check if appropriate. |
| 4517 if (cgen_->loop_nesting() > 0) { | 4530 if (cgen_->loop_nesting() > 0) { |
| 4518 Comment cmnt(masm, "[ Inlined array index load"); | 4531 Comment cmnt(masm, "[ Inlined array index load"); |
| 4519 DeferredReferenceGetKeyedValue* deferred = | 4532 DeferredReferenceGetKeyedValue* deferred = |
| 4520 new DeferredReferenceGetKeyedValue(cgen_, is_global); | 4533 new DeferredReferenceGetKeyedValue(cgen_, is_global); |
| 4521 // Load receiver and check that it is not a smi (only needed | 4534 |
| 4522 // if this is not a load from the global context) and that it | 4535 Result key = cgen_->frame()->Pop(); |
| 4523 // has the expected map. | 4536 Result receiver = cgen_->frame()->Pop(); |
| 4524 __ mov(edx, Operand(esp, kPointerSize)); | 4537 key.ToRegister(); |
| 4538 receiver.ToRegister(); | |
| 4539 | |
| 4540 // Check that the receiver is not a smi (only needed if this | |
| 4541 // is not a load from the global context) and that it has the | |
| 4542 // expected map. | |
| 4525 if (!is_global) { | 4543 if (!is_global) { |
| 4526 __ test(edx, Immediate(kSmiTagMask)); | 4544 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
| 4527 deferred->enter()->Branch(zero, not_taken); | 4545 deferred->enter()->Branch(zero, &receiver, &key, not_taken); |
| 4528 } | 4546 } |
| 4547 | |
| 4529 // Initially, use an invalid map. The map is patched in the IC | 4548 // Initially, use an invalid map. The map is patched in the IC |
| 4530 // initialization code. | 4549 // initialization code. |
| 4531 __ bind(deferred->patch_site()); | 4550 __ bind(deferred->patch_site()); |
| 4532 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 4551 __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), |
| 4533 Immediate(Factory::null_value())); | 4552 Immediate(Factory::null_value())); |
| 4534 deferred->enter()->Branch(not_equal, not_taken); | 4553 deferred->enter()->Branch(not_equal, &receiver, &key, not_taken); |
| 4535 // Load key and check that it is a smi. | 4554 |
| 4536 __ mov(eax, Operand(esp, 0)); | 4555 // Check that the key is a smi. |
| 4537 __ test(eax, Immediate(kSmiTagMask)); | 4556 __ test(key.reg(), Immediate(kSmiTagMask)); |
| 4538 deferred->enter()->Branch(not_zero, not_taken); | 4557 deferred->enter()->Branch(not_zero, &receiver, &key, not_taken); |
| 4539 // Shift to get actual index value. | 4558 |
| 4540 __ sar(eax, kSmiTagSize); | |
| 4541 // Get the elements array from the receiver and check that it | 4559 // Get the elements array from the receiver and check that it |
| 4542 // is not a dictionary. | 4560 // is not a dictionary. |
| 4543 __ mov(edx, FieldOperand(edx, JSObject::kElementsOffset)); | 4561 Result elements = cgen_->allocator()->Allocate(); |
| 4544 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 4562 ASSERT(elements.is_valid()); |
| 4563 __ mov(elements.reg(), | |
| 4564 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); | |
| 4565 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), | |
| 4545 Immediate(Factory::hash_table_map())); | 4566 Immediate(Factory::hash_table_map())); |
| 4546 deferred->enter()->Branch(equal, not_taken); | 4567 deferred->enter()->Branch(equal, &receiver, &key, not_taken); |
| 4547 // Check that key is within bounds. | 4568 |
| 4548 __ cmp(eax, FieldOperand(edx, Array::kLengthOffset)); | 4569 // Shift the key to get the actual index value and check that |
| 4549 deferred->enter()->Branch(above_equal, not_taken); | 4570 // it is within bounds. |
| 4550 // Load and check that the result is not the hole. | 4571 Result index = cgen_->allocator()->Allocate(); |
| 4551 __ mov(eax, | 4572 ASSERT(index.is_valid()); |
| 4552 Operand(edx, eax, times_4, Array::kHeaderSize - kHeapObjectTag)); | 4573 __ mov(index.reg(), key.reg()); |
| 4553 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | 4574 __ sar(index.reg(), kSmiTagSize); |
| 4554 deferred->enter()->Branch(equal, not_taken); | 4575 __ cmp(index.reg(), |
| 4576 FieldOperand(elements.reg(), Array::kLengthOffset)); | |
| 4577 deferred->enter()->Branch(above_equal, &receiver, &key, not_taken); | |
| 4578 | |
| 4579 // Load and check that the result is not the hole. We could | |
| 4580 // reuse the index or elements register for the value. | |
|
Mads Ager (chromium)
2009/01/13 07:09:09
It seems that we do use the index register for the
Kevin Millikin (Chromium)
2009/01/13 08:44:20
I want to reflect that there are two possibilities
| |
| 4581 Result value = index; | |
|
William Hesse
2009/01/13 08:41:10
I see that assignment of Results does not invalida
Kevin Millikin (Chromium)
2009/01/13 08:56:35
I'm not sure we will want to change it---copy cons
| |
| 4582 __ mov(value.reg(), Operand(elements.reg(), | |
| 4583 index.reg(), | |
| 4584 times_4, | |
| 4585 Array::kHeaderSize - kHeapObjectTag)); | |
| 4586 elements.Unuse(); | |
| 4587 index.Unuse(); | |
| 4588 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); | |
| 4589 deferred->enter()->Branch(equal, &receiver, &key, not_taken); | |
| 4555 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 4590 __ IncrementCounter(&Counters::keyed_load_inline, 1); |
| 4556 deferred->exit()->Bind(); | 4591 |
| 4592 // Restore the receiver and key to the frame and push the | |
| 4593 // result on top of it. | |
| 4594 cgen_->frame()->Push(&receiver); | |
| 4595 cgen_->frame()->Push(&key); | |
| 4596 deferred->exit()->Bind(&value); | |
| 4597 cgen_->frame()->Push(&value); | |
| 4598 | |
| 4557 } else { | 4599 } else { |
| 4600 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4601 VirtualFrame* frame = cgen_->frame(); | |
| 4558 Comment cmnt(masm, "[ Load from keyed Property"); | 4602 Comment cmnt(masm, "[ Load from keyed Property"); |
| 4559 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 4603 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 4560 if (is_global) { | 4604 if (is_global) { |
| 4561 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | 4605 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); |
| 4562 } else { | 4606 } else { |
| 4563 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4607 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
| 4564 } | 4608 } |
| 4565 // Make sure that we do not have a test instruction after the | 4609 // Make sure that we do not have a test instruction after the |
| 4566 // call. A test instruction after the call is used to | 4610 // call. A test instruction after the call is used to |
| 4567 // indicate that we have generated an inline version of the | 4611 // indicate that we have generated an inline version of the |
| 4568 // keyed load. The explicit nop instruction is here because | 4612 // keyed load. The explicit nop instruction is here because |
| 4569 // the push that follows might be peep-hole optimized away. | 4613 // the push that follows might be peep-hole optimized away. |
| 4570 __ nop(); | 4614 __ nop(); |
| 4615 frame->EmitPush(eax); // IC call leaves result in eax, push it out | |
| 4571 } | 4616 } |
| 4572 frame->EmitPush(eax); // IC call leaves result in eax, push it out | |
| 4573 break; | 4617 break; |
| 4574 } | 4618 } |
| 4575 | 4619 |
| 4576 default: | 4620 default: |
| 4577 UNREACHABLE(); | 4621 UNREACHABLE(); |
| 4578 } | 4622 } |
| 4579 } | 4623 } |
| 4580 | 4624 |
| 4581 | 4625 |
| 4582 void Reference::TakeValue(TypeofState typeof_state) { | 4626 void Reference::TakeValue(TypeofState typeof_state) { |
| (...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6031 | 6075 |
| 6032 // Slow-case: Go through the JavaScript implementation. | 6076 // Slow-case: Go through the JavaScript implementation. |
| 6033 __ bind(&slow); | 6077 __ bind(&slow); |
| 6034 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6078 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6035 } | 6079 } |
| 6036 | 6080 |
| 6037 | 6081 |
| 6038 #undef __ | 6082 #undef __ |
| 6039 | 6083 |
| 6040 } } // namespace v8::internal | 6084 } } // namespace v8::internal |
| OLD | NEW |