| 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 18 matching lines...) Expand all Loading... |
| 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 // ------------------------------------------------------------------------- | 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. | 39 // MacroAssembler implementation. |
| 300 | 40 |
| 301 MacroAssembler::MacroAssembler(void* buffer, int size) | 41 MacroAssembler::MacroAssembler(void* buffer, int size) |
| 302 : Assembler(buffer, size), | 42 : Assembler(buffer, size), |
| 303 unresolved_(0), | 43 unresolved_(0), |
| 304 generating_stub_(false), | 44 generating_stub_(false), |
| 305 allow_stub_calls_(true) { | 45 allow_stub_calls_(true) { |
| 306 } | 46 } |
| 307 | 47 |
| 308 | 48 |
| (...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 // Indicate that code has changed. | 1007 // Indicate that code has changed. |
| 1268 CPU::FlushICache(address_, size_); | 1008 CPU::FlushICache(address_, size_); |
| 1269 | 1009 |
| 1270 // Check that the code was patched as expected. | 1010 // Check that the code was patched as expected. |
| 1271 ASSERT(masm_.pc_ == address_ + size_); | 1011 ASSERT(masm_.pc_ == address_ + size_); |
| 1272 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1012 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 1273 } | 1013 } |
| 1274 | 1014 |
| 1275 | 1015 |
| 1276 } } // namespace v8::internal | 1016 } } // namespace v8::internal |
| OLD | NEW |