Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-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 3217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3228 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); | 3228 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); |
| 3229 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); | 3229 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); |
| 3230 __ jmp(&next); | 3230 __ jmp(&next); |
| 3231 __ bind(&fast); | 3231 __ bind(&fast); |
| 3232 } | 3232 } |
| 3233 context.Unuse(); | 3233 context.Unuse(); |
| 3234 tmp.Unuse(); | 3234 tmp.Unuse(); |
| 3235 | 3235 |
| 3236 // All extension objects were empty and it is safe to use a global | 3236 // All extension objects were empty and it is safe to use a global |
| 3237 // load IC call. | 3237 // load IC call. |
| 3238 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | |
| 3239 // Load the global object. | |
| 3240 LoadGlobal(); | 3238 LoadGlobal(); |
| 3241 // Setup the name register. All non-reserved registers are available. | 3239 frame_->Push(slot->var()->name()); |
| 3242 Result name = allocator_->Allocate(ecx); | 3240 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 3243 ASSERT(name.is_valid()); | 3241 ? RelocInfo::CODE_TARGET |
| 3244 __ mov(name.reg(), slot->var()->name()); | 3242 : RelocInfo::CODE_TARGET_CONTEXT; |
| 3245 RelocInfo::Mode rmode = (typeof_state == INSIDE_TYPEOF) | 3243 Result answer = frame_->CallLoadIC(mode); |
| 3246 ? RelocInfo::CODE_TARGET | |
| 3247 : RelocInfo::CODE_TARGET_CONTEXT; | |
| 3248 Result answer = frame_->CallCodeObject(ic, rmode, &name, 0); | |
| 3249 | 3244 |
| 3250 // Discard the global object. The result is in answer. | 3245 // Discard the global object. The result is in answer. |
| 3251 frame_->Drop(); | 3246 frame_->Drop(); |
| 3252 return answer; | 3247 return answer; |
| 3253 } | 3248 } |
| 3254 | 3249 |
| 3255 | 3250 |
| 3256 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { | 3251 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { |
| 3257 if (slot->type() == Slot::LOOKUP) { | 3252 if (slot->type() == Slot::LOOKUP) { |
| 3258 ASSERT(slot->var()->is_dynamic()); | 3253 ASSERT(slot->var()->is_dynamic()); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3545 for (int i = 0; i < node->properties()->length(); i++) { | 3540 for (int i = 0; i < node->properties()->length(); i++) { |
| 3546 ObjectLiteral::Property* property = node->properties()->at(i); | 3541 ObjectLiteral::Property* property = node->properties()->at(i); |
| 3547 switch (property->kind()) { | 3542 switch (property->kind()) { |
| 3548 case ObjectLiteral::Property::CONSTANT: | 3543 case ObjectLiteral::Property::CONSTANT: |
| 3549 break; | 3544 break; |
| 3550 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 3545 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 3551 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 3546 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
| 3552 // else fall through. | 3547 // else fall through. |
| 3553 case ObjectLiteral::Property::COMPUTED: { | 3548 case ObjectLiteral::Property::COMPUTED: { |
| 3554 Handle<Object> key(property->key()->handle()); | 3549 Handle<Object> key(property->key()->handle()); |
| 3555 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
| 3556 if (key->IsSymbol()) { | 3550 if (key->IsSymbol()) { |
| 3557 // Duplicate the object as the IC receiver. | 3551 // Duplicate the object as the IC receiver. |
| 3558 frame_->Dup(); | 3552 frame_->Dup(); |
| 3559 Load(property->value()); | 3553 Load(property->value()); |
| 3560 Result value = frame_->Pop(); | 3554 frame_->Push(key); |
| 3561 value.ToRegister(eax); | 3555 Result ignored = frame_->CallStoreIC(); |
| 3562 | |
| 3563 Result name = allocator_->Allocate(ecx); | |
| 3564 ASSERT(name.is_valid()); | |
| 3565 __ Set(name.reg(), Immediate(key)); | |
| 3566 Result ignored = | |
| 3567 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, | |
| 3568 &value, &name, 0); | |
| 3569 // Drop the duplicated receiver and ignore the result. | 3556 // Drop the duplicated receiver and ignore the result. |
| 3570 frame_->Drop(); | 3557 frame_->Drop(); |
| 3571 break; | 3558 break; |
| 3572 } | 3559 } |
| 3573 // Fall through | 3560 // Fall through |
| 3574 } | 3561 } |
| 3575 case ObjectLiteral::Property::PROTOTYPE: { | 3562 case ObjectLiteral::Property::PROTOTYPE: { |
| 3576 // Duplicate the object as an argument to the runtime call. | 3563 // Duplicate the object as an argument to the runtime call. |
| 3577 frame_->Dup(); | 3564 frame_->Dup(); |
| 3578 Load(property->key()); | 3565 Load(property->key()); |
| (...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5180 Label* patch_site() { return &patch_site_; } | 5167 Label* patch_site() { return &patch_site_; } |
| 5181 | 5168 |
| 5182 private: | 5169 private: |
| 5183 Label patch_site_; | 5170 Label patch_site_; |
| 5184 bool is_global_; | 5171 bool is_global_; |
| 5185 }; | 5172 }; |
| 5186 | 5173 |
| 5187 | 5174 |
| 5188 void DeferredReferenceGetKeyedValue::Generate() { | 5175 void DeferredReferenceGetKeyedValue::Generate() { |
| 5189 CodeGenerator* cgen = generator(); | 5176 CodeGenerator* cgen = generator(); |
| 5190 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
| 5191 Result receiver(cgen); | 5177 Result receiver(cgen); |
| 5192 Result key(cgen); | 5178 Result key(cgen); |
| 5193 enter()->Bind(&receiver, &key); | 5179 enter()->Bind(&receiver, &key); |
| 5194 cgen->frame()->Push(&receiver); // First IC argument. | 5180 cgen->frame()->Push(&receiver); // First IC argument. |
| 5195 cgen->frame()->Push(&key); // Second IC argument. | 5181 cgen->frame()->Push(&key); // Second IC argument. |
| 5196 | 5182 |
| 5197 // Calculate the delta from the IC call instruction to the map check | 5183 // Calculate the delta from the IC call instruction to the map check |
| 5198 // cmp instruction in the inlined version. This delta is stored in | 5184 // cmp instruction in the inlined version. This delta is stored in |
| 5199 // a test(eax, delta) instruction after the call so that we can find | 5185 // a test(eax, delta) instruction after the call so that we can find |
| 5200 // it in the IC initialization code and patch the cmp instruction. | 5186 // it in the IC initialization code and patch the cmp instruction. |
| 5201 // This means that we cannot allow test instructions after calls to | 5187 // This means that we cannot allow test instructions after calls to |
| 5202 // KeyedLoadIC stubs in other places. | 5188 // KeyedLoadIC stubs in other places. |
| 5203 Result value(cgen); | 5189 RelocInfo::Mode mode = is_global_ |
| 5204 if (is_global_) { | 5190 ? RelocInfo::CODE_TARGET_CONTEXT |
|
Kasper Lund
2009/03/25 13:25:34
4 space indent here?
| |
| 5205 value = cgen->frame()->CallCodeObject(ic, | 5191 : RelocInfo::CODE_TARGET; |
| 5206 RelocInfo::CODE_TARGET_CONTEXT, | 5192 Result value = cgen->frame()->CallKeyedLoadIC(mode); |
| 5207 0); | |
| 5208 } else { | |
| 5209 value = cgen->frame()->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | |
| 5210 } | |
| 5211 // The result needs to be specifically the eax register because the | 5193 // The result needs to be specifically the eax register because the |
| 5212 // offset to the patch site will be expected in a test eax | 5194 // offset to the patch site will be expected in a test eax |
| 5213 // instruction. | 5195 // instruction. |
| 5214 ASSERT(value.is_register() && value.reg().is(eax)); | 5196 ASSERT(value.is_register() && value.reg().is(eax)); |
| 5215 // The delta from the start of the map-compare instruction to the | 5197 // The delta from the start of the map-compare instruction to the |
| 5216 // test eax instruction. | 5198 // test eax instruction. |
| 5217 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); | 5199 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); |
| 5218 __ test(value.reg(), Immediate(-delta_to_patch_site)); | 5200 __ test(value.reg(), Immediate(-delta_to_patch_site)); |
| 5219 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 5201 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
| 5220 | 5202 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5262 break; | 5244 break; |
| 5263 } | 5245 } |
| 5264 | 5246 |
| 5265 case NAMED: { | 5247 case NAMED: { |
| 5266 // TODO(1241834): Make sure that it is safe to ignore the | 5248 // TODO(1241834): Make sure that it is safe to ignore the |
| 5267 // distinction between expressions in a typeof and not in a | 5249 // distinction between expressions in a typeof and not in a |
| 5268 // typeof. If there is a chance that reference errors can be | 5250 // typeof. If there is a chance that reference errors can be |
| 5269 // thrown below, we must distinguish between the two kinds of | 5251 // thrown below, we must distinguish between the two kinds of |
| 5270 // loads (typeof expression loads must not throw a reference | 5252 // loads (typeof expression loads must not throw a reference |
| 5271 // error). | 5253 // error). |
| 5272 VirtualFrame* frame = cgen_->frame(); | |
| 5273 Comment cmnt(masm, "[ Load from named Property"); | 5254 Comment cmnt(masm, "[ Load from named Property"); |
| 5274 Handle<String> name(GetName()); | 5255 cgen_->frame()->Push(GetName()); |
| 5256 | |
| 5275 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5257 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 5276 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | |
| 5277 // Setup the name register. | |
| 5278 Result name_reg = cgen_->allocator()->Allocate(ecx); | |
| 5279 ASSERT(name_reg.is_valid()); | |
| 5280 __ mov(name_reg.reg(), name); | |
| 5281 ASSERT(var == NULL || var->is_global()); | 5258 ASSERT(var == NULL || var->is_global()); |
| 5282 RelocInfo::Mode rmode = (var == NULL) | 5259 RelocInfo::Mode mode = (var == NULL) |
| 5283 ? RelocInfo::CODE_TARGET | 5260 ? RelocInfo::CODE_TARGET |
| 5284 : RelocInfo::CODE_TARGET_CONTEXT; | 5261 : RelocInfo::CODE_TARGET_CONTEXT; |
| 5285 Result answer = frame->CallCodeObject(ic, rmode, &name_reg, 0); | 5262 Result answer = cgen_->frame()->CallLoadIC(mode); |
| 5286 frame->Push(&answer); | 5263 cgen_->frame()->Push(&answer); |
| 5287 break; | 5264 break; |
| 5288 } | 5265 } |
| 5289 | 5266 |
| 5290 case KEYED: { | 5267 case KEYED: { |
| 5291 // TODO(1241834): Make sure that this it is safe to ignore the | 5268 // TODO(1241834): Make sure that this it is safe to ignore the |
| 5292 // distinction between expressions in a typeof and not in a typeof. | 5269 // distinction between expressions in a typeof and not in a typeof. |
| 5293 Comment cmnt(masm, "[ Load from keyed Property"); | 5270 Comment cmnt(masm, "[ Load from keyed Property"); |
| 5294 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5271 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 5295 bool is_global = var != NULL; | 5272 bool is_global = var != NULL; |
| 5296 ASSERT(!is_global || var->is_global()); | 5273 ASSERT(!is_global || var->is_global()); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5366 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 5343 __ IncrementCounter(&Counters::keyed_load_inline, 1); |
| 5367 | 5344 |
| 5368 // Restore the receiver and key to the frame and push the | 5345 // Restore the receiver and key to the frame and push the |
| 5369 // result on top of it. | 5346 // result on top of it. |
| 5370 deferred->BindExit(&receiver, &key, &value); | 5347 deferred->BindExit(&receiver, &key, &value); |
| 5371 cgen_->frame()->Push(&receiver); | 5348 cgen_->frame()->Push(&receiver); |
| 5372 cgen_->frame()->Push(&key); | 5349 cgen_->frame()->Push(&key); |
| 5373 cgen_->frame()->Push(&value); | 5350 cgen_->frame()->Push(&value); |
| 5374 | 5351 |
| 5375 } else { | 5352 } else { |
| 5376 VirtualFrame* frame = cgen_->frame(); | |
| 5377 Comment cmnt(masm, "[ Load from keyed Property"); | 5353 Comment cmnt(masm, "[ Load from keyed Property"); |
| 5378 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 5354 RelocInfo::Mode mode = is_global |
| 5379 RelocInfo::Mode rmode = is_global | 5355 ? RelocInfo::CODE_TARGET_CONTEXT |
| 5380 ? RelocInfo::CODE_TARGET_CONTEXT | 5356 : RelocInfo::CODE_TARGET; |
| 5381 : RelocInfo::CODE_TARGET; | 5357 Result answer = cgen_->frame()->CallKeyedLoadIC(mode); |
| 5382 Result answer = frame->CallCodeObject(ic, rmode, 0); | |
| 5383 // Make sure that we do not have a test instruction after the | 5358 // Make sure that we do not have a test instruction after the |
| 5384 // call. A test instruction after the call is used to | 5359 // call. A test instruction after the call is used to |
| 5385 // indicate that we have generated an inline version of the | 5360 // indicate that we have generated an inline version of the |
| 5386 // keyed load. The explicit nop instruction is here because | 5361 // keyed load. The explicit nop instruction is here because |
| 5387 // the push that follows might be peep-hole optimized away. | 5362 // the push that follows might be peep-hole optimized away. |
| 5388 __ nop(); | 5363 __ nop(); |
| 5389 frame->Push(&answer); | 5364 cgen_->frame()->Push(&answer); |
| 5390 } | 5365 } |
| 5391 break; | 5366 break; |
| 5392 } | 5367 } |
| 5393 | 5368 |
| 5394 default: | 5369 default: |
| 5395 UNREACHABLE(); | 5370 UNREACHABLE(); |
| 5396 } | 5371 } |
| 5397 } | 5372 } |
| 5398 | 5373 |
| 5399 | 5374 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 5423 } else { | 5398 } else { |
| 5424 ASSERT(slot->type() == Slot::LOCAL); | 5399 ASSERT(slot->type() == Slot::LOCAL); |
| 5425 cgen_->frame()->TakeLocalAt(slot->index()); | 5400 cgen_->frame()->TakeLocalAt(slot->index()); |
| 5426 } | 5401 } |
| 5427 } | 5402 } |
| 5428 | 5403 |
| 5429 | 5404 |
| 5430 void Reference::SetValue(InitState init_state) { | 5405 void Reference::SetValue(InitState init_state) { |
| 5431 ASSERT(cgen_->HasValidEntryRegisters()); | 5406 ASSERT(cgen_->HasValidEntryRegisters()); |
| 5432 ASSERT(!is_illegal()); | 5407 ASSERT(!is_illegal()); |
| 5433 MacroAssembler* masm = cgen_->masm(); | |
| 5434 VirtualFrame* frame = cgen_->frame(); | |
| 5435 switch (type_) { | 5408 switch (type_) { |
| 5436 case SLOT: { | 5409 case SLOT: { |
| 5437 Comment cmnt(masm, "[ Store to Slot"); | 5410 Comment cmnt(cgen_->masm(), "[ Store to Slot"); |
| 5438 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 5411 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 5439 ASSERT(slot != NULL); | 5412 ASSERT(slot != NULL); |
| 5440 cgen_->StoreToSlot(slot, init_state); | 5413 cgen_->StoreToSlot(slot, init_state); |
| 5441 break; | 5414 break; |
| 5442 } | 5415 } |
| 5443 | 5416 |
| 5444 case NAMED: { | 5417 case NAMED: { |
| 5445 Comment cmnt(masm, "[ Store to named Property"); | 5418 Comment cmnt(cgen_->masm(), "[ Store to named Property"); |
| 5446 // Call the appropriate IC code. | 5419 cgen_->frame()->Push(GetName()); |
| 5447 Handle<String> name(GetName()); | 5420 Result answer = cgen_->frame()->CallStoreIC(); |
| 5448 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 5421 cgen_->frame()->Push(&answer); |
| 5449 // TODO(1222589): Make the IC grab the values from the stack. | |
| 5450 Result argument = frame->Pop(); | |
| 5451 argument.ToRegister(eax); | |
| 5452 ASSERT(argument.is_valid()); | |
| 5453 Result property_name = cgen_->allocator()->Allocate(ecx); | |
| 5454 ASSERT(property_name.is_valid()); | |
| 5455 // Setup the name register. | |
| 5456 __ mov(property_name.reg(), name); | |
| 5457 Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, | |
| 5458 &argument, &property_name, 0); | |
| 5459 frame->Push(&answer); | |
| 5460 break; | 5422 break; |
| 5461 } | 5423 } |
| 5462 | 5424 |
| 5463 case KEYED: { | 5425 case KEYED: { |
| 5464 Comment cmnt(masm, "[ Store to keyed Property"); | 5426 Comment cmnt(cgen_->masm(), "[ Store to keyed Property"); |
| 5465 // Call IC code. | 5427 Result answer = cgen_->frame()->CallKeyedStoreIC(); |
| 5466 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 5428 cgen_->frame()->Push(&answer); |
| 5467 // TODO(1222589): Make the IC grab the values from the stack. | |
| 5468 Result arg = frame->Pop(); | |
| 5469 arg.ToRegister(eax); | |
| 5470 ASSERT(arg.is_valid()); | |
| 5471 Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, | |
| 5472 &arg, 0); | |
| 5473 frame->Push(&answer); | |
| 5474 break; | 5429 break; |
| 5475 } | 5430 } |
| 5476 | 5431 |
| 5477 default: | 5432 default: |
| 5478 UNREACHABLE(); | 5433 UNREACHABLE(); |
| 5479 } | 5434 } |
| 5480 } | 5435 } |
| 5481 | 5436 |
| 5482 | 5437 |
| 5483 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 5438 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
| (...skipping 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6988 | 6943 |
| 6989 // Slow-case: Go through the JavaScript implementation. | 6944 // Slow-case: Go through the JavaScript implementation. |
| 6990 __ bind(&slow); | 6945 __ bind(&slow); |
| 6991 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6946 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6992 } | 6947 } |
| 6993 | 6948 |
| 6994 | 6949 |
| 6995 #undef __ | 6950 #undef __ |
| 6996 | 6951 |
| 6997 } } // namespace v8::internal | 6952 } } // namespace v8::internal |
| OLD | NEW |