OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compiler/js-inlining.h" | 5 #include "src/compiler/js-inlining.h" |
6 | 6 |
7 #include "src/ast/ast-numbering.h" | 7 #include "src/ast/ast-numbering.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 DCHECK_LE(index, inlinee_context_index); | 99 DCHECK_LE(index, inlinee_context_index); |
100 if (index < inliner_inputs && index < inlinee_new_target_index) { | 100 if (index < inliner_inputs && index < inlinee_new_target_index) { |
101 // There is an input from the call, and the index is a value | 101 // There is an input from the call, and the index is a value |
102 // projection but not the context, so rewire the input. | 102 // projection but not the context, so rewire the input. |
103 Replace(use, call->InputAt(index)); | 103 Replace(use, call->InputAt(index)); |
104 } else if (index == inlinee_new_target_index) { | 104 } else if (index == inlinee_new_target_index) { |
105 // The projection is requesting the new target value. | 105 // The projection is requesting the new target value. |
106 Replace(use, new_target); | 106 Replace(use, new_target); |
107 } else if (index == inlinee_arity_index) { | 107 } else if (index == inlinee_arity_index) { |
108 // The projection is requesting the number of arguments. | 108 // The projection is requesting the number of arguments. |
109 Replace(use, jsgraph_->Int32Constant(inliner_inputs - 2)); | 109 Replace(use, jsgraph()->Int32Constant(inliner_inputs - 2)); |
110 } else if (index == inlinee_context_index) { | 110 } else if (index == inlinee_context_index) { |
111 // The projection is requesting the inlinee function context. | 111 // The projection is requesting the inlinee function context. |
112 Replace(use, context); | 112 Replace(use, context); |
113 } else { | 113 } else { |
114 // Call has fewer arguments than required, fill with undefined. | 114 // Call has fewer arguments than required, fill with undefined. |
115 Replace(use, jsgraph_->UndefinedConstant()); | 115 Replace(use, jsgraph()->UndefinedConstant()); |
116 } | 116 } |
117 break; | 117 break; |
118 } | 118 } |
119 default: | 119 default: |
120 if (NodeProperties::IsEffectEdge(edge)) { | 120 if (NodeProperties::IsEffectEdge(edge)) { |
121 edge.UpdateTo(effect); | 121 edge.UpdateTo(effect); |
122 } else if (NodeProperties::IsControlEdge(edge)) { | 122 } else if (NodeProperties::IsControlEdge(edge)) { |
123 edge.UpdateTo(control); | 123 edge.UpdateTo(control); |
124 } else if (NodeProperties::IsFrameStateEdge(edge)) { | 124 } else if (NodeProperties::IsFrameStateEdge(edge)) { |
125 edge.UpdateTo(frame_state); | 125 edge.UpdateTo(frame_state); |
(...skipping 10 matching lines...) Expand all Loading... |
136 for (Node* const input : end->inputs()) { | 136 for (Node* const input : end->inputs()) { |
137 switch (input->opcode()) { | 137 switch (input->opcode()) { |
138 case IrOpcode::kReturn: | 138 case IrOpcode::kReturn: |
139 values.push_back(NodeProperties::GetValueInput(input, 0)); | 139 values.push_back(NodeProperties::GetValueInput(input, 0)); |
140 effects.push_back(NodeProperties::GetEffectInput(input)); | 140 effects.push_back(NodeProperties::GetEffectInput(input)); |
141 controls.push_back(NodeProperties::GetControlInput(input)); | 141 controls.push_back(NodeProperties::GetControlInput(input)); |
142 break; | 142 break; |
143 case IrOpcode::kDeoptimize: | 143 case IrOpcode::kDeoptimize: |
144 case IrOpcode::kTerminate: | 144 case IrOpcode::kTerminate: |
145 case IrOpcode::kThrow: | 145 case IrOpcode::kThrow: |
146 NodeProperties::MergeControlToEnd(jsgraph_->graph(), jsgraph_->common(), | 146 NodeProperties::MergeControlToEnd(graph(), common(), input); |
147 input); | 147 Revisit(graph()->end()); |
148 Revisit(jsgraph_->graph()->end()); | |
149 break; | 148 break; |
150 default: | 149 default: |
151 UNREACHABLE(); | 150 UNREACHABLE(); |
152 break; | 151 break; |
153 } | 152 } |
154 } | 153 } |
155 DCHECK_EQ(values.size(), effects.size()); | 154 DCHECK_EQ(values.size(), effects.size()); |
156 DCHECK_EQ(values.size(), controls.size()); | 155 DCHECK_EQ(values.size(), controls.size()); |
157 | 156 |
158 // Depending on whether the inlinee produces a value, we either replace value | 157 // Depending on whether the inlinee produces a value, we either replace value |
159 // uses with said value or kill value uses if no value can be returned. | 158 // uses with said value or kill value uses if no value can be returned. |
160 if (values.size() > 0) { | 159 if (values.size() > 0) { |
161 int const input_count = static_cast<int>(controls.size()); | 160 int const input_count = static_cast<int>(controls.size()); |
162 Node* control_output = jsgraph_->graph()->NewNode( | 161 Node* control_output = graph()->NewNode(common()->Merge(input_count), |
163 jsgraph_->common()->Merge(input_count), input_count, &controls.front()); | 162 input_count, &controls.front()); |
164 values.push_back(control_output); | 163 values.push_back(control_output); |
165 effects.push_back(control_output); | 164 effects.push_back(control_output); |
166 Node* value_output = jsgraph_->graph()->NewNode( | 165 Node* value_output = graph()->NewNode( |
167 jsgraph_->common()->Phi(MachineRepresentation::kTagged, input_count), | 166 common()->Phi(MachineRepresentation::kTagged, input_count), |
168 static_cast<int>(values.size()), &values.front()); | 167 static_cast<int>(values.size()), &values.front()); |
169 Node* effect_output = jsgraph_->graph()->NewNode( | 168 Node* effect_output = |
170 jsgraph_->common()->EffectPhi(input_count), | 169 graph()->NewNode(common()->EffectPhi(input_count), |
171 static_cast<int>(effects.size()), &effects.front()); | 170 static_cast<int>(effects.size()), &effects.front()); |
172 ReplaceWithValue(call, value_output, effect_output, control_output); | 171 ReplaceWithValue(call, value_output, effect_output, control_output); |
173 return Changed(value_output); | 172 return Changed(value_output); |
174 } else { | 173 } else { |
175 ReplaceWithValue(call, call, call, jsgraph_->Dead()); | 174 ReplaceWithValue(call, call, call, jsgraph()->Dead()); |
176 return Changed(call); | 175 return Changed(call); |
177 } | 176 } |
178 } | 177 } |
179 | 178 |
180 | 179 |
181 Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, | 180 Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, |
182 int parameter_count, | 181 int parameter_count, |
183 FrameStateType frame_state_type, | 182 FrameStateType frame_state_type, |
184 Handle<SharedFunctionInfo> shared) { | 183 Handle<SharedFunctionInfo> shared) { |
185 const FrameStateFunctionInfo* state_info = | 184 const FrameStateFunctionInfo* state_info = |
186 jsgraph_->common()->CreateFrameStateFunctionInfo( | 185 common()->CreateFrameStateFunctionInfo(frame_state_type, |
187 frame_state_type, parameter_count + 1, 0, shared); | 186 parameter_count + 1, 0, shared); |
188 | 187 |
189 const Operator* op = jsgraph_->common()->FrameState( | 188 const Operator* op = common()->FrameState( |
190 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); | 189 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); |
191 const Operator* op0 = jsgraph_->common()->StateValues(0); | 190 const Operator* op0 = common()->StateValues(0); |
192 Node* node0 = jsgraph_->graph()->NewNode(op0); | 191 Node* node0 = graph()->NewNode(op0); |
193 NodeVector params(local_zone_); | 192 NodeVector params(local_zone_); |
194 for (int parameter = 0; parameter < parameter_count + 1; ++parameter) { | 193 for (int parameter = 0; parameter < parameter_count + 1; ++parameter) { |
195 params.push_back(node->InputAt(1 + parameter)); | 194 params.push_back(node->InputAt(1 + parameter)); |
196 } | 195 } |
197 const Operator* op_param = | 196 const Operator* op_param = |
198 jsgraph_->common()->StateValues(static_cast<int>(params.size())); | 197 common()->StateValues(static_cast<int>(params.size())); |
199 Node* params_node = jsgraph_->graph()->NewNode( | 198 Node* params_node = graph()->NewNode( |
200 op_param, static_cast<int>(params.size()), ¶ms.front()); | 199 op_param, static_cast<int>(params.size()), ¶ms.front()); |
201 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, | 200 return graph()->NewNode(op, params_node, node0, node0, |
202 jsgraph_->UndefinedConstant(), | 201 jsgraph()->UndefinedConstant(), node->InputAt(0), |
203 node->InputAt(0), outer_frame_state); | 202 outer_frame_state); |
204 } | 203 } |
205 | 204 |
206 Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) { | 205 Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) { |
207 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); | 206 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); |
208 Handle<SharedFunctionInfo> shared; | 207 Handle<SharedFunctionInfo> shared; |
209 frame_info.shared_info().ToHandle(&shared); | 208 frame_info.shared_info().ToHandle(&shared); |
210 | 209 |
211 Node* function = frame_state->InputAt(kFrameStateFunctionInput); | 210 Node* function = frame_state->InputAt(kFrameStateFunctionInput); |
212 | 211 |
213 // If we are inlining a tail call drop caller's frame state and an | 212 // If we are inlining a tail call drop caller's frame state and an |
214 // arguments adaptor if it exists. | 213 // arguments adaptor if it exists. |
215 frame_state = NodeProperties::GetFrameStateInput(frame_state); | 214 frame_state = NodeProperties::GetFrameStateInput(frame_state); |
216 if (frame_state->opcode() == IrOpcode::kFrameState) { | 215 if (frame_state->opcode() == IrOpcode::kFrameState) { |
217 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); | 216 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); |
218 if (frame_info.type() == FrameStateType::kArgumentsAdaptor) { | 217 if (frame_info.type() == FrameStateType::kArgumentsAdaptor) { |
219 frame_state = NodeProperties::GetFrameStateInput(frame_state); | 218 frame_state = NodeProperties::GetFrameStateInput(frame_state); |
220 } | 219 } |
221 } | 220 } |
222 | 221 |
223 const FrameStateFunctionInfo* state_info = | 222 const FrameStateFunctionInfo* state_info = |
224 jsgraph_->common()->CreateFrameStateFunctionInfo( | 223 common()->CreateFrameStateFunctionInfo( |
225 FrameStateType::kTailCallerFunction, 0, 0, shared); | 224 FrameStateType::kTailCallerFunction, 0, 0, shared); |
226 | 225 |
227 const Operator* op = jsgraph_->common()->FrameState( | 226 const Operator* op = common()->FrameState( |
228 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); | 227 BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info); |
229 const Operator* op0 = jsgraph_->common()->StateValues(0); | 228 const Operator* op0 = common()->StateValues(0); |
230 Node* node0 = jsgraph_->graph()->NewNode(op0); | 229 Node* node0 = graph()->NewNode(op0); |
231 return jsgraph_->graph()->NewNode(op, node0, node0, node0, | 230 return graph()->NewNode(op, node0, node0, node0, |
232 jsgraph_->UndefinedConstant(), function, | 231 jsgraph()->UndefinedConstant(), function, |
233 frame_state); | 232 frame_state); |
234 } | 233 } |
235 | 234 |
236 namespace { | 235 namespace { |
237 | 236 |
238 // TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo? | 237 // TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo? |
239 bool NeedsImplicitReceiver(Handle<SharedFunctionInfo> shared_info) { | 238 bool NeedsImplicitReceiver(Handle<SharedFunctionInfo> shared_info) { |
240 DisallowHeapAllocation no_gc; | 239 DisallowHeapAllocation no_gc; |
241 Isolate* const isolate = shared_info->GetIsolate(); | 240 Isolate* const isolate = shared_info->GetIsolate(); |
242 Code* const construct_stub = shared_info->construct_stub(); | 241 Code* const construct_stub = shared_info->construct_stub(); |
243 return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() && | 242 return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() && |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment, | 409 AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment, |
411 type_hint_analysis); | 410 type_hint_analysis); |
412 graph_builder.CreateGraph(false); | 411 graph_builder.CreateGraph(false); |
413 | 412 |
414 // Extract the inlinee start/end nodes. | 413 // Extract the inlinee start/end nodes. |
415 start = graph()->start(); | 414 start = graph()->start(); |
416 end = graph()->end(); | 415 end = graph()->end(); |
417 } | 416 } |
418 | 417 |
419 Node* frame_state = call.frame_state(); | 418 Node* frame_state = call.frame_state(); |
420 Node* new_target = jsgraph_->UndefinedConstant(); | 419 Node* new_target = jsgraph()->UndefinedConstant(); |
421 | 420 |
422 // Inline {JSCallConstruct} requires some additional magic. | 421 // Inline {JSCallConstruct} requires some additional magic. |
423 if (node->opcode() == IrOpcode::kJSCallConstruct) { | 422 if (node->opcode() == IrOpcode::kJSCallConstruct) { |
424 // Insert nodes around the call that model the behavior required for a | 423 // Insert nodes around the call that model the behavior required for a |
425 // constructor dispatch (allocate implicit receiver and check return value). | 424 // constructor dispatch (allocate implicit receiver and check return value). |
426 // This models the behavior usually accomplished by our {JSConstructStub}. | 425 // This models the behavior usually accomplished by our {JSConstructStub}. |
427 // Note that the context has to be the callers context (input to call node). | 426 // Note that the context has to be the callers context (input to call node). |
428 Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver. | 427 Node* receiver = jsgraph()->UndefinedConstant(); // Implicit receiver. |
429 if (NeedsImplicitReceiver(shared_info)) { | 428 if (NeedsImplicitReceiver(shared_info)) { |
430 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); | 429 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
431 Node* effect = NodeProperties::GetEffectInput(node); | 430 Node* effect = NodeProperties::GetEffectInput(node); |
432 Node* context = NodeProperties::GetContextInput(node); | 431 Node* context = NodeProperties::GetContextInput(node); |
433 Node* create = jsgraph_->graph()->NewNode( | 432 Node* create = graph()->NewNode(javascript()->Create(), call.target(), |
434 jsgraph_->javascript()->Create(), call.target(), call.new_target(), | 433 call.new_target(), context, |
435 context, frame_state_before, effect); | 434 frame_state_before, effect); |
436 NodeProperties::ReplaceEffectInput(node, create); | 435 NodeProperties::ReplaceEffectInput(node, create); |
437 // Insert a check of the return value to determine whether the return | 436 // Insert a check of the return value to determine whether the return |
438 // value | 437 // value |
439 // or the implicit receiver should be selected as a result of the call. | 438 // or the implicit receiver should be selected as a result of the call. |
440 Node* check = jsgraph_->graph()->NewNode( | 439 Node* check = graph()->NewNode( |
441 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), | 440 javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), node, |
442 node, context, node, start); | 441 context, node, start); |
443 Node* select = jsgraph_->graph()->NewNode( | 442 Node* select = |
444 jsgraph_->common()->Select(MachineRepresentation::kTagged), check, | 443 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), |
445 node, create); | 444 check, node, create); |
446 NodeProperties::ReplaceUses(node, select, check, node, node); | 445 NodeProperties::ReplaceUses(node, select, check, node, node); |
447 NodeProperties::ReplaceValueInput(select, node, 1); | 446 NodeProperties::ReplaceValueInput(select, node, 1); |
448 NodeProperties::ReplaceValueInput(check, node, 0); | 447 NodeProperties::ReplaceValueInput(check, node, 0); |
449 NodeProperties::ReplaceEffectInput(check, node); | 448 NodeProperties::ReplaceEffectInput(check, node); |
450 receiver = create; // The implicit receiver. | 449 receiver = create; // The implicit receiver. |
451 } | 450 } |
452 | 451 |
453 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a | 452 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a |
454 // normal {JSCallFunction} node so that the rest of the inlining machinery | 453 // normal {JSCallFunction} node so that the rest of the inlining machinery |
455 // behaves as if we were dealing with a regular function invocation. | 454 // behaves as if we were dealing with a regular function invocation. |
456 new_target = call.new_target(); // Retrieve new target value input. | 455 new_target = call.new_target(); // Retrieve new target value input. |
457 node->RemoveInput(call.formal_arguments() + 1); // Drop new target. | 456 node->RemoveInput(call.formal_arguments() + 1); // Drop new target. |
458 node->InsertInput(jsgraph_->graph()->zone(), 1, receiver); | 457 node->InsertInput(graph()->zone(), 1, receiver); |
459 | 458 |
460 // Insert a construct stub frame into the chain of frame states. This will | 459 // Insert a construct stub frame into the chain of frame states. This will |
461 // reconstruct the proper frame when deoptimizing within the constructor. | 460 // reconstruct the proper frame when deoptimizing within the constructor. |
462 frame_state = CreateArtificialFrameState( | 461 frame_state = CreateArtificialFrameState( |
463 node, frame_state, call.formal_arguments(), | 462 node, frame_state, call.formal_arguments(), |
464 FrameStateType::kConstructStub, info.shared_info()); | 463 FrameStateType::kConstructStub, info.shared_info()); |
465 } | 464 } |
466 | 465 |
467 // The inlinee specializes to the context from the JSFunction object. | 466 // The inlinee specializes to the context from the JSFunction object. |
468 // TODO(turbofan): We might want to load the context from the JSFunction at | 467 // TODO(turbofan): We might want to load the context from the JSFunction at |
469 // runtime in case we only know the SharedFunctionInfo once we have dynamic | 468 // runtime in case we only know the SharedFunctionInfo once we have dynamic |
470 // type feedback in the compiler. | 469 // type feedback in the compiler. |
471 Node* context = jsgraph_->Constant(handle(function->context())); | 470 Node* context = jsgraph()->Constant(handle(function->context())); |
472 | 471 |
473 // Insert a JSConvertReceiver node for sloppy callees. Note that the context | 472 // Insert a JSConvertReceiver node for sloppy callees. Note that the context |
474 // passed into this node has to be the callees context (loaded above). Note | 473 // passed into this node has to be the callees context (loaded above). Note |
475 // that the frame state passed to the JSConvertReceiver must be the frame | 474 // that the frame state passed to the JSConvertReceiver must be the frame |
476 // state _before_ the call; it is not necessary to fiddle with the receiver | 475 // state _before_ the call; it is not necessary to fiddle with the receiver |
477 // in that frame state tho, as the conversion of the receiver can be repeated | 476 // in that frame state tho, as the conversion of the receiver can be repeated |
478 // any number of times, it's not observable. | 477 // any number of times, it's not observable. |
479 if (node->opcode() == IrOpcode::kJSCallFunction && | 478 if (node->opcode() == IrOpcode::kJSCallFunction && |
480 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { | 479 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { |
481 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 480 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
482 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); | 481 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
483 Node* effect = NodeProperties::GetEffectInput(node); | 482 Node* effect = NodeProperties::GetEffectInput(node); |
484 Node* convert = jsgraph_->graph()->NewNode( | 483 Node* convert = graph()->NewNode( |
485 jsgraph_->javascript()->ConvertReceiver(p.convert_mode()), | 484 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(), |
486 call.receiver(), context, frame_state_before, effect, start); | 485 context, frame_state_before, effect, start); |
487 NodeProperties::ReplaceValueInput(node, convert, 1); | 486 NodeProperties::ReplaceValueInput(node, convert, 1); |
488 NodeProperties::ReplaceEffectInput(node, convert); | 487 NodeProperties::ReplaceEffectInput(node, convert); |
489 } | 488 } |
490 | 489 |
491 // If we are inlining a JS call at tail position then we have to pop current | 490 // If we are inlining a JS call at tail position then we have to pop current |
492 // frame state and its potential arguments adaptor frame state in order to | 491 // frame state and its potential arguments adaptor frame state in order to |
493 // make the call stack be consistent with non-inlining case. | 492 // make the call stack be consistent with non-inlining case. |
494 // After that we add a tail caller frame state which lets deoptimizer handle | 493 // After that we add a tail caller frame state which lets deoptimizer handle |
495 // the case when the outermost function inlines a tail call (it should remove | 494 // the case when the outermost function inlines a tail call (it should remove |
496 // potential arguments adaptor frame that belongs to outermost function when | 495 // potential arguments adaptor frame that belongs to outermost function when |
(...skipping 15 matching lines...) Expand all Loading... |
512 frame_state = CreateArtificialFrameState( | 511 frame_state = CreateArtificialFrameState( |
513 node, frame_state, call.formal_arguments(), | 512 node, frame_state, call.formal_arguments(), |
514 FrameStateType::kArgumentsAdaptor, shared_info); | 513 FrameStateType::kArgumentsAdaptor, shared_info); |
515 } | 514 } |
516 | 515 |
517 return InlineCall(node, new_target, context, frame_state, start, end); | 516 return InlineCall(node, new_target, context, frame_state, start, end); |
518 } | 517 } |
519 | 518 |
520 Graph* JSInliner::graph() const { return jsgraph()->graph(); } | 519 Graph* JSInliner::graph() const { return jsgraph()->graph(); } |
521 | 520 |
| 521 JSOperatorBuilder* JSInliner::javascript() const { |
| 522 return jsgraph()->javascript(); |
| 523 } |
| 524 |
| 525 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } |
| 526 |
522 } // namespace compiler | 527 } // namespace compiler |
523 } // namespace internal | 528 } // namespace internal |
524 } // namespace v8 | 529 } // namespace v8 |
OLD | NEW |