OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ | 5 #ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ |
6 #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ | 6 #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ |
7 | 7 |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/interpreter/bytecode-array-writer.h" | 9 #include "src/interpreter/bytecode-array-writer.h" |
10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 return context_register_count_; | 54 return context_register_count_; |
55 } | 55 } |
56 | 56 |
57 Register first_context_register() const; | 57 Register first_context_register() const; |
58 Register last_context_register() const; | 58 Register last_context_register() const; |
59 | 59 |
60 // Returns the number of fixed (non-temporary) registers. | 60 // Returns the number of fixed (non-temporary) registers. |
61 int fixed_register_count() const { return context_count() + locals_count(); } | 61 int fixed_register_count() const { return context_count() + locals_count(); } |
62 | 62 |
63 // Returns the number of fixed and temporary registers. | 63 // Returns the number of fixed and temporary registers. |
64 int fixed_and_temporary_register_count() const { | 64 int total_register_count() const { |
65 return fixed_register_count() + temporary_register_count(); | 65 DCHECK_LE(fixed_register_count(), |
66 } | 66 register_allocator()->maximum_register_count()); |
67 | 67 return register_allocator()->maximum_register_count(); |
68 int temporary_register_count() const { | |
69 return temporary_register_allocator()->allocation_count(); | |
70 } | 68 } |
71 | 69 |
72 Register Parameter(int parameter_index) const; | 70 Register Parameter(int parameter_index) const; |
73 | 71 |
74 // Return true if the register |reg| represents a parameter or a | |
75 // local. | |
76 bool RegisterIsParameterOrLocal(Register reg) const; | |
77 | |
78 // Returns true if the register |reg| is a live temporary register. | |
79 bool TemporaryRegisterIsLive(Register reg) const; | |
80 | |
81 // Constant loads to accumulator. | 72 // Constant loads to accumulator. |
82 BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry); | 73 BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry); |
83 BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value); | 74 BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value); |
84 BytecodeArrayBuilder& LoadLiteral(Handle<Object> object); | 75 BytecodeArrayBuilder& LoadLiteral(Handle<Object> object); |
85 BytecodeArrayBuilder& LoadUndefined(); | 76 BytecodeArrayBuilder& LoadUndefined(); |
86 BytecodeArrayBuilder& LoadNull(); | 77 BytecodeArrayBuilder& LoadNull(); |
87 BytecodeArrayBuilder& LoadTheHole(); | 78 BytecodeArrayBuilder& LoadTheHole(); |
88 BytecodeArrayBuilder& LoadTrue(); | 79 BytecodeArrayBuilder& LoadTrue(); |
89 BytecodeArrayBuilder& LoadFalse(); | 80 BytecodeArrayBuilder& LoadFalse(); |
90 | 81 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 Register output); | 175 Register output); |
185 | 176 |
186 // Push the context in accumulator as the new context, and store in register | 177 // Push the context in accumulator as the new context, and store in register |
187 // |context|. | 178 // |context|. |
188 BytecodeArrayBuilder& PushContext(Register context); | 179 BytecodeArrayBuilder& PushContext(Register context); |
189 | 180 |
190 // Pop the current context and replace with |context|. | 181 // Pop the current context and replace with |context|. |
191 BytecodeArrayBuilder& PopContext(Register context); | 182 BytecodeArrayBuilder& PopContext(Register context); |
192 | 183 |
193 // Call a JS function. The JSFunction or Callable to be called should be in | 184 // Call a JS function. The JSFunction or Callable to be called should be in |
194 // |callable|, the receiver should be in |receiver_args| and all subsequent | 185 // |callable|. The arguments should be in |args|, with the receiver in |
195 // arguments should be in registers <receiver_args + 1> to | 186 // |args[0]|. Type feedback is recorded in the |feedback_slot| in the type |
196 // <receiver_args + receiver_arg_count - 1>. Type feedback is recorded in | 187 // feedback vector. |
197 // the |feedback_slot| in the type feedback vector. | |
198 BytecodeArrayBuilder& Call( | 188 BytecodeArrayBuilder& Call( |
199 Register callable, Register receiver_args, size_t receiver_arg_count, | 189 Register callable, RegisterList args, int feedback_slot, |
200 int feedback_slot, TailCallMode tail_call_mode = TailCallMode::kDisallow); | 190 TailCallMode tail_call_mode = TailCallMode::kDisallow); |
201 | |
202 BytecodeArrayBuilder& TailCall(Register callable, Register receiver_args, | |
203 size_t receiver_arg_count, int feedback_slot) { | |
204 return Call(callable, receiver_args, receiver_arg_count, feedback_slot, | |
205 TailCallMode::kAllow); | |
206 } | |
207 | 191 |
208 // Call the new operator. The accumulator holds the |new_target|. | 192 // Call the new operator. The accumulator holds the |new_target|. |
209 // The |constructor| is in a register followed by |arg_count| | 193 // The |constructor| is in a register and arguments are in |args|. |
210 // consecutive arguments starting at |first_arg| for the constuctor | 194 BytecodeArrayBuilder& New(Register constructor, RegisterList args, |
211 // invocation. | 195 int feedback_slot); |
212 BytecodeArrayBuilder& New(Register constructor, Register first_arg, | |
213 size_t arg_count, int feedback_slot); | |
214 | 196 |
215 // Call the runtime function with |function_id|. The first argument should be | 197 // Call the runtime function with |function_id| and arguments |args|. |
216 // in |first_arg| and all subsequent arguments should be in registers | |
217 // <first_arg + 1> to <first_arg + arg_count - 1>. | |
218 BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id, | 198 BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id, |
219 Register first_arg, size_t arg_count); | 199 RegisterList args); |
| 200 // Call the runtime function with |function_id| with single argument |arg|. |
| 201 BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id, |
| 202 Register arg); |
| 203 // Call the runtime function with |function_id| with no arguments. |
| 204 BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id); |
220 | 205 |
221 // Call the runtime function with |function_id| that returns a pair of values. | 206 // Call the runtime function with |function_id| and arguments |args|, that |
222 // The first argument should be in |first_arg| and all subsequent arguments | 207 // returns a pair of values. The return values will be returned in |
223 // should be in registers <first_arg + 1> to <first_arg + arg_count - 1>. The | 208 // <first_return> and <first_return + 1>. |
224 // return values will be returned in <first_return> and <first_return + 1>. | |
225 BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id, | 209 BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id, |
226 Register first_arg, size_t arg_count, | 210 RegisterList args, |
227 Register first_return); | 211 Register first_return); |
| 212 // Call the runtime function with |function_id| with single argument |arg|. |
| 213 BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id, |
| 214 Register arg, Register first_return); |
228 | 215 |
229 // Call the JS runtime function with |context_index|. The the receiver should | 216 // Call the JS runtime function with |context_index| and arguments |args|. |
230 // be in |receiver_args| and all subsequent arguments should be in registers | 217 BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args); |
231 // <receiver + 1> to <receiver + receiver_args_count - 1>. | |
232 BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver_args, | |
233 size_t receiver_args_count); | |
234 | 218 |
235 // Operators (register holds the lhs value, accumulator holds the rhs value). | 219 // Operators (register holds the lhs value, accumulator holds the rhs value). |
236 // Type feedback will be recorded in the |feedback_slot| | 220 // Type feedback will be recorded in the |feedback_slot| |
237 BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg, | 221 BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg, |
238 int feedback_slot); | 222 int feedback_slot); |
239 | 223 |
240 // Count Operators (value stored in accumulator). | 224 // Count Operators (value stored in accumulator). |
241 // Type feedback will be recorded in the |feedback_slot| | 225 // Type feedback will be recorded in the |feedback_slot| |
242 BytecodeArrayBuilder& CountOperation(Token::Value op, int feedback_slot); | 226 BytecodeArrayBuilder& CountOperation(Token::Value op, int feedback_slot); |
243 | 227 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 // latest value. | 305 // latest value. |
322 latest_source_info_.MakeExpressionPosition(expr->position()); | 306 latest_source_info_.MakeExpressionPosition(expr->position()); |
323 } | 307 } |
324 } | 308 } |
325 | 309 |
326 void SetExpressionAsStatementPosition(Expression* expr) { | 310 void SetExpressionAsStatementPosition(Expression* expr) { |
327 if (expr->position() == kNoSourcePosition) return; | 311 if (expr->position() == kNoSourcePosition) return; |
328 latest_source_info_.MakeStatementPosition(expr->position()); | 312 latest_source_info_.MakeStatementPosition(expr->position()); |
329 } | 313 } |
330 | 314 |
| 315 void EnsureReturn(); |
| 316 |
331 // Accessors | 317 // Accessors |
332 TemporaryRegisterAllocator* temporary_register_allocator() { | 318 BytecodeRegisterAllocator* register_allocator() { |
333 return &temporary_allocator_; | 319 return ®ister_allocator_; |
334 } | 320 } |
335 const TemporaryRegisterAllocator* temporary_register_allocator() const { | 321 const BytecodeRegisterAllocator* register_allocator() const { |
336 return &temporary_allocator_; | 322 return ®ister_allocator_; |
337 } | 323 } |
338 Zone* zone() const { return zone_; } | 324 Zone* zone() const { return zone_; } |
339 | 325 |
340 void EnsureReturn(); | |
341 | |
342 static uint32_t RegisterOperand(Register reg) { | |
343 return static_cast<uint32_t>(reg.ToOperand()); | |
344 } | |
345 | |
346 static uint32_t SignedOperand(int value) { | |
347 return static_cast<uint32_t>(value); | |
348 } | |
349 | |
350 static uint32_t UnsignedOperand(int value) { | |
351 DCHECK_GE(value, 0); | |
352 return static_cast<uint32_t>(value); | |
353 } | |
354 | |
355 static uint32_t UnsignedOperand(size_t value) { | |
356 DCHECK_LE(value, kMaxUInt32); | |
357 return static_cast<uint32_t>(value); | |
358 } | |
359 | |
360 private: | 326 private: |
361 friend class BytecodeRegisterAllocator; | 327 friend class BytecodeRegisterAllocator; |
362 | 328 |
363 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, | 329 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, |
364 uint32_t operand2, uint32_t operand3)); | 330 uint32_t operand2, uint32_t operand3)); |
365 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, | 331 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, |
366 uint32_t operand2)); | 332 uint32_t operand2)); |
367 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1)); | 333 INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1)); |
368 INLINE(void Output(Bytecode bytecode, uint32_t operand0)); | 334 INLINE(void Output(Bytecode bytecode, uint32_t operand0)); |
369 INLINE(void Output(Bytecode bytecode)); | 335 INLINE(void Output(Bytecode bytecode)); |
370 | 336 |
371 INLINE(void OutputJump(Bytecode bytecode, BytecodeLabel* label)); | 337 INLINE(void OutputJump(Bytecode bytecode, BytecodeLabel* label)); |
372 INLINE(void OutputJump(Bytecode bytecode, uint32_t operand0, | 338 INLINE(void OutputJump(Bytecode bytecode, uint32_t operand0, |
373 BytecodeLabel* label)); | 339 BytecodeLabel* label)); |
374 | 340 |
375 bool RegisterIsValid(Register reg) const; | 341 bool RegisterIsValid(Register reg) const; |
376 bool OperandsAreValid(Bytecode bytecode, int operand_count, | 342 bool OperandsAreValid(Bytecode bytecode, int operand_count, |
377 uint32_t operand0 = 0, uint32_t operand1 = 0, | 343 uint32_t operand0 = 0, uint32_t operand1 = 0, |
378 uint32_t operand2 = 0, uint32_t operand3 = 0) const; | 344 uint32_t operand2 = 0, uint32_t operand3 = 0) const; |
379 | 345 |
| 346 static uint32_t RegisterOperand(Register reg) { |
| 347 return static_cast<uint32_t>(reg.ToOperand()); |
| 348 } |
| 349 |
| 350 static uint32_t SignedOperand(int value) { |
| 351 return static_cast<uint32_t>(value); |
| 352 } |
| 353 |
| 354 static uint32_t UnsignedOperand(int value) { |
| 355 DCHECK_GE(value, 0); |
| 356 return static_cast<uint32_t>(value); |
| 357 } |
| 358 |
| 359 static uint32_t UnsignedOperand(size_t value) { |
| 360 DCHECK_LE(value, kMaxUInt32); |
| 361 return static_cast<uint32_t>(value); |
| 362 } |
| 363 |
380 // Set position for return. | 364 // Set position for return. |
381 void SetReturnPosition(); | 365 void SetReturnPosition(); |
382 | 366 |
383 // Gets a constant pool entry for the |object|. | 367 // Gets a constant pool entry for the |object|. |
384 size_t GetConstantPoolEntry(Handle<Object> object); | 368 size_t GetConstantPoolEntry(Handle<Object> object); |
385 | 369 |
386 // Not implemented as the illegal bytecode is used inside internally | 370 // Not implemented as the illegal bytecode is used inside internally |
387 // to indicate a bytecode field is not valid or an error has occured | 371 // to indicate a bytecode field is not valid or an error has occured |
388 // during bytecode generation. | 372 // during bytecode generation. |
389 BytecodeArrayBuilder& Illegal(); | 373 BytecodeArrayBuilder& Illegal(); |
(...skipping 16 matching lines...) Expand all Loading... |
406 | 390 |
407 Zone* zone_; | 391 Zone* zone_; |
408 bool bytecode_generated_; | 392 bool bytecode_generated_; |
409 ConstantArrayBuilder constant_array_builder_; | 393 ConstantArrayBuilder constant_array_builder_; |
410 HandlerTableBuilder handler_table_builder_; | 394 HandlerTableBuilder handler_table_builder_; |
411 bool return_seen_in_block_; | 395 bool return_seen_in_block_; |
412 int parameter_count_; | 396 int parameter_count_; |
413 int local_register_count_; | 397 int local_register_count_; |
414 int context_register_count_; | 398 int context_register_count_; |
415 int return_position_; | 399 int return_position_; |
416 TemporaryRegisterAllocator temporary_allocator_; | 400 BytecodeRegisterAllocator register_allocator_; |
417 BytecodeArrayWriter bytecode_array_writer_; | 401 BytecodeArrayWriter bytecode_array_writer_; |
418 BytecodePipelineStage* pipeline_; | 402 BytecodePipelineStage* pipeline_; |
419 BytecodeSourceInfo latest_source_info_; | 403 BytecodeSourceInfo latest_source_info_; |
420 | 404 |
421 static int const kNoFeedbackSlot = 0; | 405 static int const kNoFeedbackSlot = 0; |
422 | 406 |
423 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder); | 407 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder); |
424 }; | 408 }; |
425 | 409 |
426 } // namespace interpreter | 410 } // namespace interpreter |
427 } // namespace internal | 411 } // namespace internal |
428 } // namespace v8 | 412 } // namespace v8 |
429 | 413 |
430 #endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ | 414 #endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ |
OLD | NEW |