| 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
| 32 #include "debug.h" | 32 #include "debug.h" |
| 33 #include "runtime.h" | 33 #include "runtime.h" |
| 34 #include "serialize.h" | 34 #include "serialize.h" |
| 35 | 35 |
| 36 namespace v8 { namespace internal { | 36 namespace v8 { namespace internal { |
| 37 | 37 |
| 38 // ------------------------------------------------------------------------- |
| 39 // VirtualFrame implementation. |
| 40 |
| 41 #define __ masm_-> |
| 42 |
| 43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) { |
| 44 ASSERT(cgen->scope() != NULL); |
| 45 |
| 46 masm_ = cgen->masm(); |
| 47 frame_local_count_ = cgen->scope()->num_stack_slots(); |
| 48 parameter_count_ = cgen->scope()->num_parameters(); |
| 49 height_ = 0; |
| 50 } |
| 51 |
| 52 |
| 53 VirtualFrame::VirtualFrame(VirtualFrame* original) { |
| 54 ASSERT(original != NULL); |
| 55 |
| 56 masm_ = original->masm_; |
| 57 frame_local_count_ = original->frame_local_count_; |
| 58 parameter_count_ = original->parameter_count_; |
| 59 height_ = original->height_; |
| 60 } |
| 61 |
| 62 |
| 63 void VirtualFrame::Forget(int count) { |
| 64 ASSERT(count >= 0); |
| 65 ASSERT(height_ >= count); |
| 66 height_ -= count; |
| 67 } |
| 68 |
| 69 |
| 70 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
| 71 ASSERT(masm_ == expected->masm_); |
| 72 ASSERT(frame_local_count_ == expected->frame_local_count_); |
| 73 ASSERT(parameter_count_ == expected->parameter_count_); |
| 74 ASSERT(height_ == expected->height_); |
| 75 } |
| 76 |
| 77 |
| 78 void VirtualFrame::Enter() { |
| 79 Comment cmnt(masm_, "[ Enter JS frame"); |
| 80 __ push(ebp); |
| 81 __ mov(ebp, Operand(esp)); |
| 82 |
| 83 // Store the context and the function in the frame. |
| 84 __ push(esi); |
| 85 __ push(edi); |
| 86 |
| 87 // Clear the function slot when generating debug code. |
| 88 if (FLAG_debug_code) { |
| 89 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); |
| 90 } |
| 91 } |
| 92 |
| 93 |
| 94 void VirtualFrame::Exit() { |
| 95 Comment cmnt(masm_, "[ Exit JS frame"); |
| 96 // Record the location of the JS exit code for patching when setting |
| 97 // break point. |
| 98 __ RecordJSReturn(); |
| 99 |
| 100 // Avoid using the leave instruction here, because it is too |
| 101 // short. We need the return sequence to be a least the size of a |
| 102 // call instruction to support patching the exit code in the |
| 103 // debugger. See VisitReturnStatement for the full return sequence. |
| 104 __ mov(esp, Operand(ebp)); |
| 105 __ pop(ebp); |
| 106 } |
| 107 |
| 108 |
| 109 void VirtualFrame::AllocateLocals() { |
| 110 if (frame_local_count_ > 0) { |
| 111 Comment cmnt(masm_, "[ Allocate space for locals"); |
| 112 __ Set(eax, Immediate(Factory::undefined_value())); |
| 113 for (int i = 0; i < frame_local_count_; i++) { |
| 114 __ push(eax); |
| 115 } |
| 116 } |
| 117 } |
| 118 |
| 119 |
| 120 // ------------------------------------------------------------------------- |
| 121 // JumpTarget implementation. |
| 122 |
| 123 JumpTarget::JumpTarget(CodeGenerator* cgen) { |
| 124 ASSERT(cgen != NULL); |
| 125 expected_frame_ = NULL; |
| 126 code_generator_ = cgen; |
| 127 masm_ = cgen->masm(); |
| 128 } |
| 129 |
| 130 |
| 131 JumpTarget::JumpTarget() |
| 132 : expected_frame_(NULL), |
| 133 code_generator_(NULL), |
| 134 masm_(NULL) { |
| 135 } |
| 136 |
| 137 |
| 138 void JumpTarget::set_code_generator(CodeGenerator* cgen) { |
| 139 ASSERT(cgen != NULL); |
| 140 ASSERT(code_generator_ == NULL); |
| 141 code_generator_ = cgen; |
| 142 masm_ = cgen->masm(); |
| 143 } |
| 144 |
| 145 |
| 146 bool JumpTarget::IsActualFunctionReturn() { |
| 147 return (this == &code_generator_->function_return_ && |
| 148 !code_generator_->function_return_is_shadowed_); |
| 149 } |
| 150 |
| 151 |
| 152 void JumpTarget::Jump() { |
| 153 // Precondition: there is a current frame. There may or may not be an |
| 154 // expected frame at the label. |
| 155 ASSERT(code_generator_ != NULL); |
| 156 ASSERT(masm_ != NULL); |
| 157 |
| 158 VirtualFrame* current_frame = code_generator_->frame(); |
| 159 ASSERT(current_frame != NULL); |
| 160 |
| 161 if (expected_frame_ == NULL) { |
| 162 expected_frame_ = current_frame; |
| 163 code_generator_->set_frame(NULL); |
| 164 // The frame at the actual function return will always have height |
| 165 // zero. |
| 166 if (IsActualFunctionReturn()) expected_frame_->height_ = 0; |
| 167 } else { |
| 168 // No code needs to be emitted to merge to the expected frame at the |
| 169 // actual function return. |
| 170 if (!IsActualFunctionReturn()) current_frame->MergeTo(expected_frame_); |
| 171 code_generator_->delete_frame(); |
| 172 } |
| 173 |
| 174 __ jmp(&label_); |
| 175 // Postcondition: there is no current frame but there is an expected frame |
| 176 // at the label. |
| 177 } |
| 178 |
| 179 |
| 180 void JumpTarget::Branch(Condition cc, Hint hint) { |
| 181 // Precondition: there is a current frame. There may or may not be an |
| 182 // expected frame at the label. |
| 183 ASSERT(code_generator_ != NULL); |
| 184 ASSERT(masm_ != NULL); |
| 185 |
| 186 VirtualFrame* current_frame = code_generator_->frame(); |
| 187 ASSERT(current_frame != NULL); |
| 188 |
| 189 if (expected_frame_ == NULL) { |
| 190 expected_frame_ = new VirtualFrame(current_frame); |
| 191 // The frame at the actual function return will always have height |
| 192 // zero. |
| 193 if (IsActualFunctionReturn()) expected_frame_->height_ = 0; |
| 194 } else { |
| 195 // No code needs to be emitted to merge to the expected frame at the |
| 196 // actual function return. |
| 197 if (!IsActualFunctionReturn()) current_frame->MergeTo(expected_frame_); |
| 198 } |
| 199 |
| 200 __ j(cc, &label_, hint); |
| 201 // Postcondition: there is both a current frame and an expected frame at |
| 202 // the label and they match. |
| 203 } |
| 204 |
| 205 |
| 206 void JumpTarget::Call() { |
| 207 // Precondition: there is a current frame, and there is no expected frame |
| 208 // at the label. |
| 209 ASSERT(code_generator_ != NULL); |
| 210 ASSERT(masm_ != NULL); |
| 211 ASSERT(!IsActualFunctionReturn()); |
| 212 |
| 213 VirtualFrame* current_frame = code_generator_->frame(); |
| 214 ASSERT(current_frame != NULL); |
| 215 ASSERT(expected_frame_ == NULL); |
| 216 |
| 217 expected_frame_ = new VirtualFrame(current_frame); |
| 218 // Adjust the expected frame's height to account for the return address |
| 219 // pushed by the call instruction. |
| 220 expected_frame_->height_++; |
| 221 |
| 222 __ call(&label_); |
| 223 |
| 224 // Postcondition: there is both a current frame and an expected frame at |
| 225 // the label. The current frame is one shorter than the one at the label |
| 226 // (which contains the 'return address', ie, the eip register and possibly |
| 227 // cs register). |
| 228 } |
| 229 |
| 230 |
| 231 void JumpTarget::Bind() { |
| 232 ASSERT(code_generator_ != NULL); |
| 233 ASSERT(masm_ != NULL); |
| 234 |
| 235 // Precondition: there is either a current frame or an expected frame at |
| 236 // the label (and possibly both). The label is unbound. |
| 237 VirtualFrame* current_frame = code_generator_->frame(); |
| 238 ASSERT(current_frame != NULL || expected_frame_ != NULL); |
| 239 ASSERT(!label_.is_bound()); |
| 240 |
| 241 if (expected_frame_ == NULL) { |
| 242 expected_frame_ = new VirtualFrame(current_frame); |
| 243 // The frame at the actual function return will always have height |
| 244 // zero. |
| 245 if (IsActualFunctionReturn()) expected_frame_->height_ = 0; |
| 246 } else if (current_frame == NULL) { |
| 247 code_generator_->set_frame(new VirtualFrame(expected_frame_)); |
| 248 } else { |
| 249 // No code needs to be emitted to merge to the expected frame at the |
| 250 // actual function return. |
| 251 if (!IsActualFunctionReturn()) current_frame->MergeTo(expected_frame_); |
| 252 } |
| 253 |
| 254 __ bind(&label_); |
| 255 // Postcondition: there is both a current frame and an expected frame at |
| 256 // the label and they match. The label is bound. |
| 257 } |
| 258 |
| 259 |
| 260 // ------------------------------------------------------------------------- |
| 261 // ShadowTarget implementation. |
| 262 |
| 263 ShadowTarget::ShadowTarget(JumpTarget* original) { |
| 264 ASSERT(original != NULL); |
| 265 original_target_ = original; |
| 266 original_pos_ = original->label()->pos_; |
| 267 original_expected_frame_ = original->expected_frame(); |
| 268 |
| 269 // We do not call Unuse() on the orginal jump target, because we do not |
| 270 // want to delete the expected frame. |
| 271 original->label()->pos_ = 0; |
| 272 original->set_expected_frame(NULL); |
| 273 #ifdef DEBUG |
| 274 is_shadowing_ = true; |
| 275 #endif |
| 276 } |
| 277 |
| 278 |
| 279 void ShadowTarget::StopShadowing() { |
| 280 ASSERT(is_shadowing_); |
| 281 ASSERT(is_unused()); |
| 282 |
| 283 set_code_generator(original_target_->code_generator()); |
| 284 label_.pos_ = original_target_->label()->pos_; |
| 285 expected_frame_ = original_target_->expected_frame(); |
| 286 |
| 287 original_target_->label()->pos_ = original_pos_; |
| 288 original_target_->set_expected_frame(original_expected_frame_); |
| 289 |
| 290 #ifdef DEBUG |
| 291 is_shadowing_ = false; |
| 292 #endif |
| 293 } |
| 294 |
| 295 #undef __ |
| 296 |
| 297 |
| 298 // ------------------------------------------------------------------------- |
| 299 // MacroAssembler implementation. |
| 300 |
| 38 MacroAssembler::MacroAssembler(void* buffer, int size) | 301 MacroAssembler::MacroAssembler(void* buffer, int size) |
| 39 : Assembler(buffer, size), | 302 : Assembler(buffer, size), |
| 40 unresolved_(0), | 303 unresolved_(0), |
| 41 generating_stub_(false), | 304 generating_stub_(false), |
| 42 allow_stub_calls_(true) { | 305 allow_stub_calls_(true) { |
| 43 } | 306 } |
| 44 | 307 |
| 45 | 308 |
| 46 static void RecordWriteHelper(MacroAssembler* masm, | 309 static void RecordWriteHelper(MacroAssembler* masm, |
| 47 Register object, | 310 Register object, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 void Print() { | 366 void Print() { |
| 104 PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", | 367 PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", |
| 105 object_.code(), addr_.code(), scratch_.code()); | 368 object_.code(), addr_.code(), scratch_.code()); |
| 106 } | 369 } |
| 107 #endif | 370 #endif |
| 108 | 371 |
| 109 // Minor key encoding in 12 bits of three registers (object, address and | 372 // Minor key encoding in 12 bits of three registers (object, address and |
| 110 // scratch) OOOOAAAASSSS. | 373 // scratch) OOOOAAAASSSS. |
| 111 class ScratchBits: public BitField<uint32_t, 0, 4> {}; | 374 class ScratchBits: public BitField<uint32_t, 0, 4> {}; |
| 112 class AddressBits: public BitField<uint32_t, 4, 4> {}; | 375 class AddressBits: public BitField<uint32_t, 4, 4> {}; |
| 113 class ObjectBits: public BitField<uint32_t, 8, 4> { | 376 class ObjectBits: public BitField<uint32_t, 8, 4> {}; |
| 114 }; | |
| 115 | 377 |
| 116 Major MajorKey() { return RecordWrite; } | 378 Major MajorKey() { return RecordWrite; } |
| 117 | 379 |
| 118 int MinorKey() { | 380 int MinorKey() { |
| 119 // Encode the registers. | 381 // Encode the registers. |
| 120 return ObjectBits::encode(object_.code()) | | 382 return ObjectBits::encode(object_.code()) | |
| 121 AddressBits::encode(addr_.code()) | | 383 AddressBits::encode(addr_.code()) | |
| 122 ScratchBits::encode(scratch_.code()); | 384 ScratchBits::encode(scratch_.code()); |
| 123 } | 385 } |
| 124 }; | 386 }; |
| (...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 // Indicate that code has changed. | 1267 // Indicate that code has changed. |
| 1006 CPU::FlushICache(address_, size_); | 1268 CPU::FlushICache(address_, size_); |
| 1007 | 1269 |
| 1008 // Check that the code was patched as expected. | 1270 // Check that the code was patched as expected. |
| 1009 ASSERT(masm_.pc_ == address_ + size_); | 1271 ASSERT(masm_.pc_ == address_ + size_); |
| 1010 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1272 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 1011 } | 1273 } |
| 1012 | 1274 |
| 1013 | 1275 |
| 1014 } } // namespace v8::internal | 1276 } } // namespace v8::internal |
| OLD | NEW |